Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / PinProtectionHelper.cs / 1 / PinProtectionHelper.cs
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{
using System;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using Microsoft.InfoCards.Diagnostics;
using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace;
//
// Summary:
// Structure for carrying details of the PKCS5 algorithm used
// to produce a key.
//
internal class PinProtectionHelper
{
//
// Number of PKCS5 iterations to perform when generating the encryption key
//
const int InfoCardPKCS5IterationCount = 1000;
//
// Size of InfoCard Salt in bytes
//
public const int SaltSize = 16;
//
// Size of AES block length in bytes
//
const int AESBlockByteLength = 16;
//
// Size of AES key length in bytes
//
const int AESKeyByteLength = 32;
//
// Version for pin protection scheme
//
const byte EncryptForPinProtectionVersion = 2;
//
// PKCS5 implementation
// NOTE: Need to use Rfc2898DeriveBytes
//
PasswordDeriveBytes m_pkcs5;
byte[] m_key;
RijndaelManaged m_aes = new RijndaelManaged();
//
// Summary
// Generates a key and associated details from a pin using random salt a IV.
//
// Parameters
// pin - User passphrase used to generate the key using PKCS5
//
public PinProtectionHelper( string pin )
{
RNGCryptoServiceProvider prov = new RNGCryptoServiceProvider();
byte[] salt = new byte[ SaltSize ];
prov.GetBytes( salt );
//
// Generate the key using PKCS5
//
m_pkcs5 = new PasswordDeriveBytes( pin, salt, "SHA256", (int) InfoCardPKCS5IterationCount );
m_key = m_pkcs5.GetBytes( AESKeyByteLength );
//
// Setup the AES algorithm
//
m_aes.Padding = PaddingMode.PKCS7;
m_aes.Mode = CipherMode.CBC;
m_aes.BlockSize = AESBlockByteLength * 8;
m_aes.KeySize = m_key.Length * 8;
m_aes.GenerateIV();
}
//
// Summary
// Generates a key and associated details from a pin and the serialized parameters.
//
// Parameters
// pin - User passphrase used to generate the key using PKCS5
// serializedParameters - Information about how the key was generated
//
// Remarks
// Reads the serialized form below to constur
// Version | Salt | Interations | IV | Encrypted Data
// 0 1 17 21 37
// Version : 1 byte
// Salt : 16 bytes
// Iterations : 4 bytes
// IV : 16 bytes
// EncData : ?? bytes of unicode encrypted using AES256
//
private const int VersionOffset = 0;
private const int SaltOffset = 1;
private const int IterationsOffset = 17;
private const int IVOffset = 21;
private const int EncryptedDataOffset = 37;
public PinProtectionHelper( string pin, byte[] serializedParameters )
{
if( EncryptForPinProtectionVersion != serializedParameters[ 0 ] )
{
throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ServiceCardDecryptionFailed ) ) );
}
//
// Generate the key using PKCS5
//
byte[] salt = new byte[ SaltSize ];
Array.Copy( serializedParameters, SaltOffset, salt, 0, SaltSize );
UInt32 iterations = BitConverter.ToUInt32( serializedParameters, IterationsOffset );
m_pkcs5 = new PasswordDeriveBytes( pin, salt, "SHA256", (int) iterations );
m_key = m_pkcs5.GetBytes( AESKeyByteLength );
//
// Setup the AES algorithm
//
m_aes.Padding = PaddingMode.PKCS7;
m_aes.Mode = CipherMode.CBC;
m_aes.BlockSize = AESBlockByteLength * 8;
m_aes.KeySize = m_key.Length * 8;
byte[] iv = new byte[ AESBlockByteLength ];
//
// Extract the IV from the byte array
//
Array.Copy( serializedParameters, IVOffset, iv, 0, iv.Length );
m_aes.IV = iv;
}
//
// Summary
// Encrypts an array of bytes using the pin protection scheme and AES
//
// Parameters
// toEncrypt - bytes to be encrypted
// pkcs5 - Information about how the key was generated
//
// Remarks
// Encrypt each block to look like:
// Version | Salt | Interations | IV | Encrypted Data
// 0 1 17 21 37
// Version : 1 byte
// Salt : 16 bytes
// Iterations : 4 bytes
// IV : 16 bytes
// EncData : 48 bytes of unicode encrypted using AES256
// The size of the encrypted data can be computed by the following
//
// CipherText = PlainText(bytes) + BlockSize(bytes) - (PlainText MOD BlockSize )
//
// So, In this case EncData = 32(MasterKeySize) + 16(BlockSize) - ( 32 MOD 16 ) = 48
//
// NOTE: Change the EncryotedMasterKeySize method if the logic in this function changes
//
public byte[] EncryptMasterKey( byte[] toEncrypt )
{
byte[] encryptedKey = Encrypt( toEncrypt );
using( MemoryStream digest = new MemoryStream() )
{
digest.WriteByte( EncryptForPinProtectionVersion );
digest.Write( m_pkcs5.Salt, 0, m_pkcs5.Salt.Length );
digest.Write( System.BitConverter.GetBytes( (UInt32) m_pkcs5.IterationCount ), 0, 4 );
digest.Write( m_aes.IV, 0, m_aes.IV.Length );
digest.Write( encryptedKey, 0, encryptedKey.Length );
return digest.ToArray();
}
}
//
// Summary
// Returns the size of the encrypted master key
//
// Remarks
// EncryptedMasterKeySize = 1(Version)+ 16(Salt)+4(Iterations)+16(IV)+48(EncData)
// NOTE: the algorithm changes if the algorithm to create the digest in EncryptMasterKey changes
public static int EncryptedMasterKeySize
{
get
{
return ( 1 + SaltSize + 4 +
AESBlockByteLength +
InfoCard.MasterKeySize +
AESBlockByteLength -
( InfoCard.MasterKeySize % AESBlockByteLength ) );
}
}
//
// Summary
// Encrypts an array of bytes using the pin protection scheme and AES
//
// Parameters
// toEncrypt - bytes to be encrypted
// pkcs5 - Information about how the key was generated
//
// Remarks
//
public byte[] Encrypt( byte[] toEncrypt )
{
using( ICryptoTransform encryptor = m_aes.CreateEncryptor( m_key, m_aes.IV ) )
{
using( MemoryStream digest = new MemoryStream() )
{
try
{
using( CryptoStream cs = new CryptoStream( digest, encryptor, CryptoStreamMode.Write ) )
{
//
// Encrypt the claim value
//
cs.Write( toEncrypt, 0, toEncrypt.Length );
cs.FlushFinalBlock();
return digest.ToArray();
}
}
catch( CryptographicException e )
{
throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ServiceCardEncryptionFailed ), e ) );
}
}
}
}
//
// Summary
// Encrypts an array of bytes using the pin protection scheme and AES
//
// Parameters
// toEncrypt - bytes to be encrypted
// pkcs5 - Information about how the key was generated
//
// Remarks
// Each block looks like the following:
//
public byte[] DecryptMasterKey( byte[] toDecrypt )
{
byte[] encrypted = new byte[ toDecrypt.Length - EncryptedDataOffset ];
Array.Copy( toDecrypt, EncryptedDataOffset, encrypted, 0, toDecrypt.Length - EncryptedDataOffset );
return Decrypt( encrypted );
}
//
// Summary
// Encrypts an array of bytes using the pin protection scheme and AES
//
// Parameters
// encrypted - bytes to be decrypted
//
public byte[] Decrypt( byte[] encrypted )
{
using( ICryptoTransform decryptor = m_aes.CreateDecryptor( m_key, m_aes.IV ) )
{
using( MemoryStream digest = new MemoryStream( encrypted ) )
{
try
{
using( CryptoStream cs = new CryptoStream( digest, decryptor, CryptoStreamMode.Read ) )
{
byte[] decrypted = new byte[ encrypted.Length ];
int count = cs.Read( decrypted, 0, decrypted.Length );
//
// Truncate to the subarray containing the plain text
//
byte[] result = new byte[ count ];
Array.Copy( decrypted, result, count );
return result;
}
}
catch( CryptographicException e )
{
throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ServiceCardDecryptionFailed ), e ) );
}
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DispatcherOperation.cs
- SecurityStateEncoder.cs
- ThemeDictionaryExtension.cs
- ParseHttpDate.cs
- StateMachineTimers.cs
- RelationshipEndCollection.cs
- cryptoapiTransform.cs
- DisposableCollectionWrapper.cs
- StylusDownEventArgs.cs
- TransactionalPackage.cs
- SafeFileHandle.cs
- ConstrainedDataObject.cs
- SecurityAttributeGenerationHelper.cs
- printdlgexmarshaler.cs
- DisplayMemberTemplateSelector.cs
- InplaceBitmapMetadataWriter.cs
- ReadOnlyDictionary.cs
- ToolBarButtonClickEvent.cs
- Classification.cs
- FormsAuthenticationConfiguration.cs
- KoreanLunisolarCalendar.cs
- ZipIOModeEnforcingStream.cs
- SqlDataSourceStatusEventArgs.cs
- HostProtectionException.cs
- BufferAllocator.cs
- EventLogException.cs
- IMembershipProvider.cs
- PointAnimationClockResource.cs
- HttpWebResponse.cs
- CookielessHelper.cs
- ImageClickEventArgs.cs
- DependencyPropertyHelper.cs
- Collection.cs
- SqlDataSourceView.cs
- ModelPerspective.cs
- AssemblyBuilderData.cs
- EventSinkHelperWriter.cs
- WinInetCache.cs
- TextOptions.cs
- GatewayIPAddressInformationCollection.cs
- CachedPathData.cs
- Image.cs
- WindowsComboBox.cs
- XmlHierarchicalDataSourceView.cs
- FolderBrowserDialog.cs
- PerfCounters.cs
- ActivityDesignerAccessibleObject.cs
- NotCondition.cs
- TextDecorationCollection.cs
- TrustManagerMoreInformation.cs
- ADRoleFactoryConfiguration.cs
- BufferedGraphicsContext.cs
- NumericUpDownAcceleration.cs
- SafeThreadHandle.cs
- Point3DCollection.cs
- RC2CryptoServiceProvider.cs
- SignatureHelper.cs
- MULTI_QI.cs
- ConfigXmlAttribute.cs
- DbParameterCollection.cs
- ZoneButton.cs
- SystemColors.cs
- XmlRootAttribute.cs
- ConnectionInterfaceCollection.cs
- MissingMethodException.cs
- VBCodeProvider.cs
- RestHandlerFactory.cs
- KeyedCollection.cs
- DefaultCommandExtensionCallback.cs
- NumberAction.cs
- MultiViewDesigner.cs
- MetadataSource.cs
- PersonalizationProviderCollection.cs
- XmlSerializationReader.cs
- LinqDataSource.cs
- HttpModuleCollection.cs
- sqlser.cs
- DoubleLink.cs
- EntityWithKeyStrategy.cs
- PolyLineSegmentFigureLogic.cs
- ObjectIDGenerator.cs
- ClientCultureInfo.cs
- CaseStatement.cs
- HelpEvent.cs
- XmlNamedNodeMap.cs
- TcpProcessProtocolHandler.cs
- IconHelper.cs
- LocalizationParserHooks.cs
- ColumnPropertiesGroup.cs
- TemplateParser.cs
- GroupBoxAutomationPeer.cs
- DataColumnMappingCollection.cs
- ExtensionQuery.cs
- MailBnfHelper.cs
- CompositeScriptReference.cs
- ValueConversionAttribute.cs
- EventLogEntryCollection.cs
- HandlerMappingMemo.cs
- SmiMetaData.cs
- DocumentPaginator.cs