zoukankan      html  css  js  c++  java
  • 图解使用Win8Api进行Metro风格的程序开发十三加解密

    我们紧接着上篇,这篇将介绍如何使用Cryptography WinRT API,来实现
    加解密.

    本篇将介绍如下9个方面:
    a)CryptographicBuffer类来转换和编码字符串
    b)HashAlgorithmProvider 类 支持哈希算法
    c)MacAlgorithmProvider 类 支持HMAC算法
    d)KeyDerivationAlgorithmProvider类 支持对称算法
    e)SymmetricKeyAlgorithmProvider类 支持对称算法
    f)EncryptedAndAuthenticatedData类 支持认证加密算法
    g)AsymmetricKeyAlgorithmProvider类 支持非对称算法
    h)AsymmetricKeyAlgorithmProvider类 支持签名算法
    i)DataProtectionProvider类

    我们的创建的步骤如下:
    1)为了组织文件方便,我们先建一个文件夹CryptoWinRT
    2)向文件夹中添加如下文件:
    CryptographicBufferTest.xaml,HashAlgorithms.xaml,
    HmacAlgorithms.xaml,KeyDerivation.xaml,
    CipherAlgorithms.xaml,AuthenticatedEncryptionAlgorithms.xaml,
    EncryptAndDecrypt.xaml,SignAndVerifySignature.xaml,
    AsynchronousDataProtection.xaml,AsynchronousDataProtectionWithStreams.xaml,
    创建方法请参照前一篇.
    3)此时的解决方案结构如下:

    4)向我们的DataSource添加导航所需要的信息
      修改我们的SampleDataSource.cs文件中的SampleDataSource类中的代码,
      代码如下: 

    View Code
            public SampleDataSource()
            {
                #region Group1
                var group1 = new SampleDataGroup("FilePicker",
                  "Use Windows.Storage.Pickers API",
                  "Access and save files using the file picker",
                  "Assets/FilePicker.jpg",
                  "");
                group1.Items.Add(new SampleDataItem("FilePicker-PickASinglePhoto",
                        "Pick a single photo",
                        "only one file can selected,file type is jpg,jpeg,png",
                        "Assets/FilePicker.jpg",
                        "only one file can selected ",
                        "",
                        group1,
                        typeof(PickASinglePhoto)));
                group1.Items.Add(new SampleDataItem("FilePicker-PickMultipleFiles",
                        "Pick multiple files",
                        "you can pick multiple files",
                        "Assets/FilePicker.jpg",
                        "pick multiple files",
                        "",
                        group1,
                        typeof(PickMultipleFiles)));
                group1.Items.Add(new SampleDataItem("FilePicker-PickAFolder",
                        "Pick a folder",
                        "you can pick a folder",
                        "Assets/FilePicker.jpg",
                        "Pick a folder",
                        "",
                        group1,
                        typeof(PickAFolder)));
                group1.Items.Add(new SampleDataItem("FilePicker-SaveAFile",
                        "Save a file",
                        "you can save a file",
                        "Assets/FilePicker.jpg",
                        "Save a file",
                        "",
                        group1,
                        typeof(SaveAFile)));
                this.AllGroups.Add(group1);
                #endregion
    
                #region Group2
                var group2 = new SampleDataGroup("FileAceess",
               "Using Windows.Storage API",
               "File access",
               "Assets/FileAccess.jpg",
               "");
                group2.Items.Add(new SampleDataItem("FileAceess-CreatingAFile",
                        "Create a file",
                        "Using CreateFileAsync Create a file",
                        "Assets/FileAccess.jpg",
                        "Using CreateFileAsync",
                        "",
                        group2,
                        typeof(CreatingAFile)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-WritingAndReadingText",
                   "Write And Read A Text",
                   "Using WriteTextAsync,ReadTextAsync Write And Read  Text",
                   "Assets/FileAccess.jpg",
                   "Using WriteTextAsync,ReadTextAsync",
                   "",
                   group2,
                   typeof(WritingAndReadingText)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-WritingAndReadingBytes",
                  "Writing and reading bytes in a file",
                  "Using WriteBufferAsync,ReadBufferAsync Write And Read bytes",
                  "Assets/FileAccess.jpg",
                  "Using WriteBufferAsync,ReadBufferAsync",
                  "",
                  group2,
                  typeof(WritingAndReadingBytes)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-WritingAndReadingUsingStream",
                    "Writing and reading using a stream",
                    "Using OpenAsync Writing and reading using a stream",
                    "Assets/FileAccess.jpg",
                    "Using OpenAsync",
                    "",
                    group2,
                    typeof(WritingAndReadingUsingStream)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-DisplayingFileProperties",
                    "Displaying file properties",
                    "Using GetBasicPropertiesAsync  Get File Properties",
                    "Assets/FileAccess.jpg",
                    "Using GetBasicPropertiesAsync",
                    "",
                    group2,
                    typeof(DisplayingFileProperties)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-PersistingAccess",
                    "Persisting access to a storage item for future use",
                    "Using MostRecentlyUsedList",
                    "Assets/FileAccess.jpg",
                    "Using MostRecentlyUsedList",
                    "",
                    group2,
                    typeof(PersistingAccess)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-CopyAFile",
                    "Copy a file",
                    "Using CopyAsync Copy a file",
                    "Assets/FileAccess.jpg",
                    "Using CopyAsync",
                    "",
                    group2,
                    typeof(CopyAFile)));
    
                group2.Items.Add(new SampleDataItem("FileAceess-DeleteAFile",
                    "Delete a file",
                    "Using DeleteAsync Delete a file",
                    "Assets/FileAccess.jpg",
                    "Using DeleteAsync",
                    "",
                    group2,
                    typeof(DeleteAFile)));
    
                this.AllGroups.Add(group2);
                #endregion
    
                #region Group3
                var group3 = new SampleDataGroup("AccountPictureName",
                  "Use Windows.System.UserProfile API",
                  "Account Picture Name",
                  "Assets/AccountPictureName.jpg",
                  "");
                group3.Items.Add(new SampleDataItem("AccountPictureName-GetUserDisplayName",
                        "Get User DisplayName",
                        "Use UserInformation.GetDisplayNameAsync Get User DisplayName",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.GetDisplayNameAsync",
                        "",
                        group3,
                        typeof(GetUserDisplayName)));
                group3.Items.Add(new SampleDataItem("AccountPictureName-GetUserFirstLastName",
                        "Get First Last Name",
                        "Use UserInformation.GetFirstNameAsync,GetLastNameAsync Get First Name",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.GetFirstNameAsync ",
                        "",
                        group3,
                        typeof(GetUserFirstLastName)));
                group3.Items.Add(new SampleDataItem("AccountPictureName-GetAccountPicture",
                        "Get Account Picture",
                        "Use UserInformation.GetAccountPicture Get Account Picture",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.GetAccountPicture",
                        "",
                        group3,
                        typeof(GetAccountPicture)));
                group3.Items.Add(new SampleDataItem("AccountPictureName-SetAccountPictureAndListen",
                        "Set AccountPicture And Listen",
                        "Use UserInformation.SetAccountPicturesAsync Set AccountPicture",
                        "Assets/AccountPictureName.jpg",
                        "Use UserInformation.SetAccountPicturesAsync",
                        "",
                        group3,
                        typeof(SetAccountPictureAndListen)));
                this.AllGroups.Add(group3);
                #endregion
    
                #region Group4
                var group4 = new SampleDataGroup("ApplicationSettings",
                  "ApplicationSettings",
                  " Use the Windows.UI.ApplicationSettings namespace and WinJS.UI.SettingsFlyout",
                  "Assets/ApplicationSettings.jpg",
                  "");
                group4.Items.Add(new SampleDataItem("ApplicationSettings-Default",
                        "Default behavior with no settings integration",
                        "Default behavior ",
                        "Assets/ApplicationSettings.jpg",
                        "Default behavior with no settings integration",
                        "",
                        group4,
                        typeof(Default)));
                group4.Items.Add(new SampleDataItem("ApplicationSettings-AddSettings",
                        "Add settings commands to the settings charm",
                        "Add settings",
                        "Assets/ApplicationSettings.jpg",
                        "Add settings commands to the settings charm ",
                        "",
                        group4,
                        typeof(AddSettings)));
    
                this.AllGroups.Add(group4);
                #endregion
    
                #region Group5
                var Group5 = new SampleDataGroup("AssociationLaunching",
                  "Use Windows.System.Launcher API",
                  "Association Launching",
                  "Assets/AssociationLaunching.jpg",
                  "");
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-LaunchFile",
                        "Launching a file",
                        "Use Windows.System.Launcher.LaunchFileAsync",
                        "Assets/AssociationLaunching.jpg",
                        "Use Windows.System.Launcher.LaunchFileAsync",
                        "",
                        Group5,
                        typeof(LaunchFile)));
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-LaunchUri",
                        "Launching a URI",
                        "Use Windows.System.Launcher.LaunchUriAsync",
                        "Assets/AssociationLaunching.jpg",
                        "Use Windows.System.Launcher.LaunchUriAsync",
                        "",
                        Group5,
                        typeof(LaunchUri)));
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-ReceiveFile",
                        "Receiving a file",
                        "Receiving a file",
                        "Assets/AssociationLaunching.jpg",
                        "Receiving a file",
                        "",
                        Group5,
                        typeof(ReceiveFile)));
                Group5.Items.Add(new SampleDataItem("AssociationLaunching-ReceiveUri",
                        "Receiving a URI",
                        "Receiving a URI",
                        "Assets/AssociationLaunching.jpg",
                        "Receiving a URI",
                        "",
                        Group5,
                        typeof(ReceiveUri)));
                this.AllGroups.Add(Group5);
                #endregion
    
                #region Group6
                var Group6 = new SampleDataGroup("BackgroundTransfer",
                  "Use Windows.Networking.BackgroundTransfer API",
                  "BackgroundDownloader And BackgroundUploader",
                  "Assets/BackgroundTransfer.jpg",
                  "");
                Group6.Items.Add(new SampleDataItem("BackgroundTransfer-DownloadFile",
                        "Download Files",
                        "Use BackgroundDownloader",
                        "Assets/BackgroundTransfer.jpg",
                        "BackgroundDownloader",
                        "",
                        Group6,
                        typeof(DownloadFile)));
                Group6.Items.Add(new SampleDataItem("BackgroundTransfer-UploadFile",
                        "Upload Files",
                        "Use BackgroundUploader",
                        "Assets/BackgroundTransfer.jpg",
                        "BackgroundUploader",
                        "",
                        Group6,
                        typeof(UploadFile)));
    
                this.AllGroups.Add(Group6);
                #endregion
    
                #region Group7
                var Group7 = new SampleDataGroup("Clipboard",
                  "Use Windows.ApplicationModel.DataTransfer API",
                  "ClipboardOperation",
                  "Assets/Clipboard.jpg",
                  "");
                Group7.Items.Add(new SampleDataItem("Clipboard-CopyAndPasteText",
                        "Copy and paste text",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(CopyAndPasteText)));
                Group7.Items.Add(new SampleDataItem("Clipboard-CopyAndPasteImage",
                        "Copy and paste an image",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(CopyAndPasteImage)));
                Group7.Items.Add(new SampleDataItem("Clipboard-CopyAndPasteFile",
                        "Copy and paste files",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(CopyAndPasteFile)));
                Group7.Items.Add(new SampleDataItem("Clipboard-OtherClipboardOperation",
                        "Other Clipboard operations",
                        "Use Clipboard.GetContent,Clipboard.SetContent",
                        "Assets/Clipboard.jpg",
                        "Clipboard.GetContent,Clipboard.SetContent",
                        "",
                        Group7,
                        typeof(OtherClipboardOperation)));
    
                this.AllGroups.Add(Group7);
                #endregion
    
                #region Group8
                var Group8 = new SampleDataGroup("Compression",
                  "Use Windows.Storage.Compression API",
                  "Compression And Decompression",
                  "Assets/Compression.jpg",
                  "");
                Group8.Items.Add(new SampleDataItem("Compression-CompressionAndDecompression",
                        "Compression And Decompression",
                        "Use Windows.Storage.Compression API",
                        "Assets/Compression.jpg",
                        "Compression And Decompression",
                        "",
                        Group8,
                        typeof(CompressionAndDecompression)));
    
                this.AllGroups.Add(Group8);
                #endregion
    
                #region Group9
                var Group9 = new SampleDataGroup("MediaButtons",
                  "Use Windows.Media API",
                  "Media Buttons",
                  "Assets/MediaButtons.jpg",
                  "");
                Group9.Items.Add(new SampleDataItem("MediaButtons-MediaEvents",
                        "Media Events",
                        "Use Windows.Media API",
                        "Assets/MediaButtons.jpg",
                        "Listening to hardware media transport events",
                        "",
                        Group9,
                        typeof(MediaEvents)));
    
                this.AllGroups.Add(Group9);
                #endregion
    
                #region Group10
                var Group10 = new SampleDataGroup("ContactPicker",
                  "Use Windows.ApplicationModel.Contacts API",
                  "Contact Picker",
                  "Assets/ContactPicker.jpg",
                  "");
                Group10.Items.Add(new SampleDataItem("ContactPicker-SinglePicker",
                        "Pick a single contact",
                        "Use ContactPicker.PickSingleContactAsync()",
                        "Assets/ContactPicker.jpg",
                        "PickSingleContactAsync",
                        "",
                        Group10,
                        typeof(SinglePicker)));
                Group10.Items.Add(new SampleDataItem("ContactPicker-MultiplePicker",
                        "Pick multiple contacts",
                        "Use ContactPicker.PickMultipleContactsAsync()",
                        "Assets/ContactPicker.jpg",
                        "PickMultipleContactsAsync",
                        "",
                        Group10,
                        typeof(MultiplePicker)));
    
                this.AllGroups.Add(Group10);
                #endregion
    
                #region Group11
                var Group11 = new SampleDataGroup("ContextMenu",
                  "Use Windows.UI.Popups API",
                  "Context Menu",
                  "Assets/ContextMenu.jpg",
                  "");
                Group11.Items.Add(new SampleDataItem("ContextMenu-ShowAContextMenu",
                        "Show a context menu",
                        "Show a context menu",
                        "Assets/ContextMenu.jpg",
                        "Show a context menu",
                        "",
                        Group11,
                        typeof(ShowAContextMenu)));
                Group11.Items.Add(new SampleDataItem("ContextMenu-ReplaceADefaultContextMenu",
                        "Replace a default context menu",
                        "Replace a default context menu",
                        "Assets/ContextMenu.jpg",
                        "Replace a default context menu",
                        "",
                        Group11,
                        typeof(ReplaceADefaultContextMenu)));
    
                this.AllGroups.Add(Group11);
                #endregion
    
                #region Group12
                var Group12 = new SampleDataGroup("CryptoWinRT",
                  "Use Cryptography WinRT API",
                  "CryptoWinRT",
                  "Assets/CryptoWinRT.jpg",
                  "");
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-CryptographicBuffer",
                        "CryptographicBuffer",
                        "CryptographicBuffer",
                        "Assets/CryptoWinRT.jpg",
                        "CryptographicBuffer",
                        "",
                        Group12,
                        typeof(CryptographicBufferTest)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-HashAlgorithms",
                        "HashAlgorithms",
                        "HashAlgorithms",
                        "Assets/CryptoWinRT.jpg",
                        "HashAlgorithms",
                        "",
                        Group12,
                        typeof(HashAlgorithms)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-HmacAlgorithms",
                        "HmacAlgorithms",
                        "HmacAlgorithms",
                        "Assets/CryptoWinRT.jpg",
                        "HmacAlgorithms",
                        "",
                        Group12,
                        typeof(HmacAlgorithms)));
    
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-KeyDerivation",
                        "KeyDerivation",
                        "KeyDerivation",
                        "Assets/CryptoWinRT.jpg",
                        "KeyDerivation",
                        "",
                        Group12,
                        typeof(KeyDerivation)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-CipherAlgorithms",
                            "CipherAlgorithms",
                            "CipherAlgorithms",
                            "Assets/CryptoWinRT.jpg",
                            "CipherAlgorithms",
                            "",
                            Group12,
                            typeof(CipherAlgorithms)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-AuthenticatedEncryptionAlgorithms",
                             "AuthenticatedEncryptionAlgorithms",
                             "AuthenticatedEncryptionAlgorithms",
                             "Assets/CryptoWinRT.jpg",
                             "AuthenticatedEncryptionAlgorithms",
                             "",
                             Group12,
                             typeof(AuthenticatedEncryptionAlgorithms)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-EncryptAndDecrypt",
                             "EncryptAndDecrypt",
                             "EncryptAndDecrypt",
                             "Assets/CryptoWinRT.jpg",
                             "EncryptAndDecrypt",
                             "",
                             Group12,
                             typeof(EncryptAndDecrypt)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-SignAndVerifySignature",
                             "SignAndVerifySignature",
                             "SignAndVerifySignature",
                             "Assets/CryptoWinRT.jpg",
                             "SignAndVerifySignature",
                             "",
                             Group12,
                             typeof(SignAndVerifySignature)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-AsynchronousDataProtection",
                             "AsynchronousDataProtection",
                             "AsynchronousDataProtection",
                             "Assets/CryptoWinRT.jpg",
                             "AsynchronousDataProtection",
                             "",
                             Group12,
                             typeof(AsynchronousDataProtection)));
                Group12.Items.Add(new SampleDataItem("CryptoWinRT-AsynchronousDataProtectionWithStreams",
                             "AsynchronousDataProtectionWithStreams",
                             "AsynchronousDataProtectionWithStreams",
                             "Assets/CryptoWinRT.jpg",
                             "AsynchronousDataProtectionWithStreams",
                             "",
                             Group12,
                             typeof(AsynchronousDataProtectionWithStreams)));
                this.AllGroups.Add(Group12);
                #endregion
            }

    5)我们的导航这样就做好了,效果图:

      点击 CryptoWinRT

    6)使用CryptographicBuffer类来转换和编码字符串
    修改CryptographicBufferTest的xaml:

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock x:Name="InputTextBlock1"  TextWrapping="Wrap" Grid.Row="0" Style="{StaticResource BodyTextStyle}" HorizontalAlignment="Left" >
                    CryptographicBuffer - the use of the CryptographicBuffer class in WinRT.
                </TextBlock>
                <StackPanel Orientation="Horizontal" Margin="0,10,0,0" Grid.Row="1">
                    <Button Name="RunSample" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class CryptographicBufferTest : Page
        {
            public CryptographicBufferTest()
            {
                this.InitializeComponent();
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                IBuffer buffer;
                OutputText.Text = "";
    
                byte[] ByteArray = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                String base64String = "UmVmYWN0b3I=";
                String hexString = "19891026";
                String inputString = "Refactor";
    
                //创建包含随机数据的缓冲区
                buffer = CryptographicBuffer.GenerateRandom(32);
                OutputText.Text += "GenerateRandom\n";
                //将缓冲区编码为十六进制字符串
                OutputText.Text += "  Buffer: " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                // 从输入字节数组创建缓冲区
                buffer = CryptographicBuffer.CreateFromByteArray(ByteArray);
                OutputText.Text += "CreateFromByteArray\n";
                OutputText.Text += "  Buffer: " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                // 对 Base64 编码进行解码
                buffer = CryptographicBuffer.DecodeFromBase64String(base64String);
                OutputText.Text += "DecodeFromBase64String\n";
                OutputText.Text += "  Base64 String: " + base64String + "\n";
                OutputText.Text += "  Buffer:        " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                // 对十六进制编码的字符串进行解码
                buffer = CryptographicBuffer.DecodeFromHexString(hexString);
                OutputText.Text += "DecodeFromHexString\n";
                OutputText.Text += "  Hex String: " + hexString + "\n";
                OutputText.Text += "  Buffer:     " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                // 将字符串转换为已编码的缓冲区
                buffer = CryptographicBuffer.ConvertStringToBinary(inputString, BinaryStringEncoding.Utf16BE);
                OutputText.Text += "ConvertStringToBinary (Utf16BE)\n";
                OutputText.Text += "  String: " + inputString + "\n";
                OutputText.Text += "  Buffer: " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                buffer = CryptographicBuffer.ConvertStringToBinary(inputString, BinaryStringEncoding.Utf16LE);
                OutputText.Text += "ConvertStringToBinary (Utf16LE)\n";
                OutputText.Text += "  String: " + inputString + "\n";
                OutputText.Text += "  Buffer: " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                buffer = CryptographicBuffer.ConvertStringToBinary(inputString, BinaryStringEncoding.Utf8);
                OutputText.Text += "ConvertStringToBinary (Utf8)\n";
                OutputText.Text += "  String: " + inputString + "\n";
                OutputText.Text += "  Buffer: " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
                buffer = CryptographicBuffer.DecodeFromBase64String(base64String);
                OutputText.Text += "DecodeFromBase64String \n";
                OutputText.Text += "  String: " + base64String + "\n";
                OutputText.Text += "  Buffer (Hex): " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
                OutputText.Text += "  Buffer (Base64): " + CryptographicBuffer.EncodeToBase64String(buffer) + "\n\n";
    
                buffer = CryptographicBuffer.DecodeFromHexString(hexString);
                OutputText.Text += "DecodeFromHexString \n";
                OutputText.Text += "  String: " + hexString + "\n";
                OutputText.Text += "  Buffer: " + CryptographicBuffer.EncodeToHexString(buffer) + "\n\n";
    
            }
        }

    7)使用HashAlgorithmProvider 类 支持哈希算法
     
    修改HashAlgorithms.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Text="Hash Algorithms - how to use the Hash algorithms that are included in WinRT for the various suported hashing algorithms." Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left"/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="200">
                            <ComboBoxItem>
                                <x:String>MD5</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SHA512</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class HashAlgorithms : Page
        {
            public HashAlgorithms()
            {
                this.InitializeComponent();
    
                AlgorithmNames.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                OutputText.Text = "";
    
                String inputString = "Refactor";
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
    
                // 加密哈希算法提供程序
                HashAlgorithmProvider Algorithm = HashAlgorithmProvider.OpenAlgorithm(algName);
    
                IBuffer vector = CryptographicBuffer.ConvertStringToBinary(inputString, BinaryStringEncoding.Utf8);
                OutputText.Text += "\n*** Sample Hash Algorithm: " + Algorithm.AlgorithmName + "\n";
                OutputText.Text += "    Initial string: Refactor\n";
    
                // 哈希二进制数据
                IBuffer digest = Algorithm.HashData(vector);
    
                if (digest.Length != Algorithm.HashLength)
                {
                    OutputText.Text += "HashAlgorithmProvider failed to generate a hash of proper length!\n";
                    return;
                }
                //将缓冲区编码为16进制字符串
                OutputText.Text += "    Hash:  " + CryptographicBuffer.EncodeToHexString(digest) + "\n";
    
                CryptographicHash reusableHash = Algorithm.CreateHash();
    
                reusableHash.Append(vector);
    
                IBuffer digest2 = reusableHash.GetValueAndReset();
    
                if (!CryptographicBuffer.Compare(digest, digest2))
                {
                    OutputText.Text += "CryptographicHash failed to generate the same hash data!\n";
                    return;
                }
    
                reusableHash.Append(vector);
                digest2 = reusableHash.GetValueAndReset();
    
                if (!CryptographicBuffer.Compare(digest, digest2))
                {
                    OutputText.Text += "Reusable CryptographicHash failed to generate the same hash data!\n";
                    return;
                }
            }
        }


    8)使用MacAlgorithmProvider 类 支持HMAC算法
    修改HmacAlgorithms.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Text="Hmac Algorithms - how to use the HMAC algorithms to sign and verify data using the WinRT APIs." Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left"/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="200">
                            <ComboBoxItem>
                                <x:String>HMAC_MD5</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>HMAC_SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>HMAC_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>HMAC_SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>HMAC_SHA512</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class HmacAlgorithms : Page
        {
            public HmacAlgorithms()
            {
                this.InitializeComponent();
                AlgorithmNames.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
                OutputText.Text = "";
    
                String Message = "Refactor";
                MacAlgorithmProvider Algorithm = MacAlgorithmProvider.OpenAlgorithm(algName);
    
                OutputText.Text += "*** Sample Hmac Algorithm: " + Algorithm.AlgorithmName + "\n";
    
                IBuffer keymaterial = CryptographicBuffer.GenerateRandom(Algorithm.MacLength);
                //创建key
                CryptographicKey hmacKey = Algorithm.CreateKey(keymaterial);
    
                // 对加密解密进行签名
                IBuffer signature = CryptographicEngine.Sign(
                                                hmacKey,
                                                CryptographicBuffer.ConvertStringToBinary(Message, BinaryStringEncoding.Utf8)
                                                );
    
                OutputText.Text += "    Signature:  " + CryptographicBuffer.EncodeToHexString(signature) + "\n";
    
                hmacKey = Algorithm.CreateKey(keymaterial);
    
                bool IsAuthenticated = Windows.Security.Cryptography.Core.CryptographicEngine.VerifySignature(
                                                hmacKey,
                                                CryptographicBuffer.ConvertStringToBinary(Message, BinaryStringEncoding.Utf8),
                                                signature
                                                );
    
                if (!IsAuthenticated)
                {
                    OutputText.Text += "HashAlgorithmProvider failed to generate a hash of proper length!\n";
                    return;
                }
            }
        }


    9)使用KeyDerivationAlgorithmProvider类 支持对称算法
    修改KeyDerivation.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" Text="Key Derivation - how to derive Keys for various Algorithms and Key Sizes using the WinRT APIs."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="250" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>PBKDF2_MD5</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>PBKDF2_SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>PBKDF2_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SP800_108_CTR_HMAC_MD5</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SP800_108_CTR_HMAC_SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SP800_108_CTR_HMAC_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SP800_56A_CONCAT_SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>SP800_56A_CONCAT_SHA512</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <ComboBox Name="KeySizes" Width="100" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>64</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>256</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class KeyDerivation : Page
        {
            public KeyDerivation()
            {
                this.InitializeComponent();
                AlgorithmNames.SelectedIndex = 0;
                KeySizes.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
                IBuffer Secret = CryptographicBuffer.ConvertStringToBinary("Refactor", BinaryStringEncoding.Utf8);
                UInt32 TargetSize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());
                OutputText.Text = "";
                //派生密钥时使用的参数
                KeyDerivationParameters Params;
    
                if (algName.Contains("PBKDF2"))
                {
                    Params = KeyDerivationParameters.BuildForPbkdf2(
                                    CryptographicBuffer.GenerateRandom(16), 
                                    10000  
                                    );
                }
                else if (algName.Contains("SP800_108"))
                {
                    Params = KeyDerivationParameters.BuildForSP800108(
                                     CryptographicBuffer.ConvertStringToBinary("Refactor", BinaryStringEncoding.Utf8),  
                                     CryptographicBuffer.DecodeFromHexString("19891026")  
                                     );
                }
                else if (algName.Contains("SP800_56A"))
                {
                    Params = KeyDerivationParameters.BuildForSP80056a(
                        CryptographicBuffer.ConvertStringToBinary("Refactor", BinaryStringEncoding.Utf8),
                        CryptographicBuffer.ConvertStringToBinary("Refactor1", BinaryStringEncoding.Utf8),
                        CryptographicBuffer.ConvertStringToBinary("Refactor2", BinaryStringEncoding.Utf8),
                        CryptographicBuffer.ConvertStringToBinary("Refactor3", BinaryStringEncoding.Utf8),
                        CryptographicBuffer.ConvertStringToBinary("Refactor4", BinaryStringEncoding.Utf8)
                        );
                }
                else
                {
                    OutputText.Text += "    An invalid algorithm was specified.\n";
                    return;
                }
    
                // Create a KeyDerivationAlgorithmProvider object for the algorithm specified on input.
                KeyDerivationAlgorithmProvider Algorithm = KeyDerivationAlgorithmProvider.OpenAlgorithm(algName);
    
                OutputText.Text += "*** Sample Kdf Algorithm: " + Algorithm.AlgorithmName + "\n";
                OutputText.Text += "    Secrect Size: " + Secret.Length + "\n";
                OutputText.Text += "    Target Size: " + TargetSize + "\n";
    
                // Create a key.
                CryptographicKey key = Algorithm.CreateKey(Secret);
    
                // Derive a key from the created key.
                IBuffer derived = CryptographicEngine.DeriveKeyMaterial(key, Params, TargetSize);
                OutputText.Text += "    Derived  " + derived.Length + " bytes\n";
                OutputText.Text += "    Derived: " + CryptographicBuffer.EncodeToHexString(derived) + "\n";
            }
        }


    10)使用SymmetricKeyAlgorithmProvider类 支持对称算法
    修改CipherAlgorithms.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}" Text="Cipher Algorithms -  how generate symmetric keys and use them for encryption and decryption using the WinRT APIs."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="200" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>AES_CBC</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>AES_ECB</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>AES_CBC_PKCS7</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>AES_ECB_PKCS7</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>DES_CBC</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>DES_ECB</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>3DES_CBC</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>3DES_ECB</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>3DES_CBC_PKCS7</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>3DES_ECB_PKCS7</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RC2_CBC</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RC2_ECB</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RC4</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <ComboBox Name="KeySizes" Width="100" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>64</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>128</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>192</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>512</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class CipherAlgorithms : Page
        {
            public CipherAlgorithms()
            {
                this.InitializeComponent();
                AlgorithmNames.SelectedIndex = 0;
                KeySizes.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
                UInt32 keySize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());
                OutputText.Text = "";
    
                IBuffer encrypted;
                IBuffer decrypted;
                IBuffer buffer;
                IBuffer iv = null;
                String blockCookie = "1234567812345678"; // 16 bytes
    
                // 对称密钥提供程序
                SymmetricKeyAlgorithmProvider Algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);
    
                OutputText.Text += "\n*** Sample Cipher Encryption\n";
                OutputText.Text += "    Algorithm Name: " + Algorithm.AlgorithmName + "\n";
                OutputText.Text += "    Key Size: " + keySize + "\n";
                OutputText.Text += "    Block length: " + Algorithm.BlockLength + "\n";
    
                IBuffer keymaterial = CryptographicBuffer.GenerateRandom((keySize + 7) / 8);
                CryptographicKey key;
                try
                {
                    //创建对称键
                    key = Algorithm.CreateSymmetricKey(keymaterial);
                }
                catch (ArgumentException ex)
                {
                    OutputText.Text += ex.Message + "\n";
                    OutputText.Text += "An invalid key size was selected for the given algorithm.\n";
                    return;
                }
    
                if (algName.Contains("CBC"))
                    iv = CryptographicBuffer.GenerateRandom(Algorithm.BlockLength);
    
                buffer = CryptographicBuffer.ConvertStringToBinary(blockCookie, BinaryStringEncoding.Utf8);
    
                encrypted = CryptographicEngine.Encrypt(key, buffer, iv);
    
                OutputText.Text += "    Plain text: " + buffer.Length + " bytes\n";
                OutputText.Text += "    Encrypted: " + encrypted.Length + " bytes\n";
    
                CryptographicKey key2 = Algorithm.CreateSymmetricKey(keymaterial);
    
                if (key.KeySize != key2.KeySize)
                {
                    OutputText.Text += "CreateSymmetricKey failed!  The imported key's size did not match the original's!";
                    return;
                }
    
                decrypted =CryptographicEngine.Decrypt(key2, encrypted, iv);
    
                if (!CryptographicBuffer.Compare(decrypted, buffer))
                {
                    OutputText.Text += "Decrypted does not match original!";
                    return;
                }
            }
        }


    11)使用EncryptedAndAuthenticatedData类 支持认证加密算法
    修改AuthenticatedEncryptionAlgorithms.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}" Text="Authenticated Encryption Algorithms -how to perform Authenticated Encryption and Decryption with the WinRT APIs."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="200" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>AES_GCM</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>AES_CCM</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <ComboBox Name="KeySizes" Width="100" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>128</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>256</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class AuthenticatedEncryptionAlgorithms : Page
        {
            static byte[] NonceBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    
            public AuthenticatedEncryptionAlgorithms()
            {
                this.InitializeComponent();
                AlgorithmNames.SelectedIndex = 0;
                KeySizes.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            IBuffer GetNonce()
            {
                NonceBytes[0]++;
                for (int i = 0; i < NonceBytes.Length - 1; i++)
                {
                    if (NonceBytes[i] == 255)
                    {
                        NonceBytes[i + 1]++;
                    }
                }
    
                return CryptographicBuffer.CreateFromByteArray(NonceBytes);
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
                UInt32 keySize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());
                OutputText.Text = "";
    
                IBuffer Decrypted;
                IBuffer Data;
                IBuffer Nonce;
                String Cookie = "Refactor";
    
                Data = CryptographicBuffer.ConvertStringToBinary(Cookie, BinaryStringEncoding.Utf16LE);
    
                SymmetricKeyAlgorithmProvider Algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);
    
                OutputText.Text += "*** Sample Authenticated Encryption\n";
                OutputText.Text += "    Algorithm Name: " + Algorithm.AlgorithmName + "\n";
                OutputText.Text += "    Key Size: " + keySize + "\n";
                OutputText.Text += "    Block length: " + Algorithm.BlockLength + "\n";
    
                IBuffer keymaterial = CryptographicBuffer.GenerateRandom((keySize + 7) / 8);
                CryptographicKey key = Algorithm.CreateSymmetricKey(keymaterial);
    
                Nonce = GetNonce();
    
                EncryptedAndAuthenticatedData Encrypted = CryptographicEngine.EncryptAndAuthenticate(key, Data, Nonce, null);
    
                OutputText.Text += "    Plain text: " + Data.Length + " bytes\n";
                OutputText.Text += "    Encrypted: " + Encrypted.EncryptedData.Length + " bytes\n";
                OutputText.Text += "    AuthTag: " + Encrypted.AuthenticationTag.Length + " bytes\n";
    
                CryptographicKey key2 = Algorithm.CreateSymmetricKey(keymaterial);
    
                if (key.KeySize != key2.KeySize)
                {
                    OutputText.Text += "CreateSymmetricKey failed!  The imported key's size did not match the original's!";
                    return;
                }
    
                Decrypted = CryptographicEngine.DecryptAndAuthenticate(key2, Encrypted.EncryptedData, Nonce, Encrypted.AuthenticationTag, null);
    
                if (!CryptographicBuffer.Compare(Decrypted, Data))
                {
                    OutputText.Text += "Decrypted does not match original!";
                    return;
                }
            }
        }


    12)使用AsymmetricKeyAlgorithmProvider类 支持非对称算法
    修改EncryptAndDecrypt.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}" Text="Encrypt and Decrypt -  how to Encrypt and Decrypt data with the WinRT APIs for supported Algorithms and Key Sizes."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="200" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>RSA_PKCS1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSA_OAEP_SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSA_OAEP_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSA_OAEP_SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSA_OAEP_SHA512</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <ComboBox Name="KeySizes" Width="100" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>512</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>1024</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>2048</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>4096</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class EncryptAndDecrypt : Page
        {
            public EncryptAndDecrypt()
            {
                this.InitializeComponent();
                AlgorithmNames.SelectedIndex = 0;
                KeySizes.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
                UInt32 KeySize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());
                OutputText.Text = "";
    
                IBuffer Data;
                String cookie = "Refactor";
    
                switch (AlgorithmNames.SelectedIndex)
                {
                    case 0:
                        Data = CryptographicBuffer.ConvertStringToBinary(cookie, BinaryStringEncoding.Utf16LE);
                        break;
                    case 1:
                        Data = CryptographicBuffer.GenerateRandom(1024 / 8 - 2 * 20 - 2);
                        break;
                    case 2:
                        Data = CryptographicBuffer.GenerateRandom(1024 / 8 - 2 * (256 / 8) - 2);
                        break;
                    case 3:
                        Data = CryptographicBuffer.GenerateRandom(2048 / 8 - 2 * (384 / 8) - 2);
                        break;
                    case 4:
                        Data = CryptographicBuffer.GenerateRandom(2048 / 8 - 2 * (512 / 8) - 2);
                        break;
                    default:
                        OutputText.Text += "An invalid algorithm was selected";
                        return;
                }
    
                IBuffer Encrypted;
                IBuffer Decrypted;
                IBuffer blobOfPublicKey;
                IBuffer blobOfKeyPair;
    
                AsymmetricKeyAlgorithmProvider Algorithm = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);
    
                OutputText.Text += "*** Sample Encryption Algorithm\n";
                OutputText.Text += "    Algorithm Name: " + Algorithm.AlgorithmName + "\n";
                OutputText.Text += "    Key Size: " + KeySize + "\n";
    
                CryptographicKey keyPair = Algorithm.CreateKeyPair(KeySize);
    
                try
                {
                    Encrypted = CryptographicEngine.Encrypt(keyPair, Data, null);
                }
                catch (ArgumentException ex)
                {
                    OutputText.Text += ex.Message + "\n";
                    OutputText.Text += "An invalid key size was selected for the given algorithm.\n";
                    return;
                }
    
                OutputText.Text += "    Plain text: " + Data.Length + " bytes\n";
                OutputText.Text += "    Encrypted: " + Encrypted.Length + " bytes\n";
    
                blobOfPublicKey = keyPair.ExportPublicKey();
                blobOfKeyPair = keyPair.Export();
    
                CryptographicKey keyPublic = Algorithm.ImportPublicKey(blobOfPublicKey);
                if (keyPublic.KeySize != keyPair.KeySize)
                {
                    OutputText.Text += "ImportPublicKey failed!  The imported key's size did not match the original's!";
                    return;
                }
    
                keyPair = Algorithm.ImportKeyPair(blobOfKeyPair);
    
                // Check the key size of the imported key.
                if (keyPublic.KeySize != keyPair.KeySize)
                {
                    OutputText.Text += "ImportKeyPair failed!  The imported key's size did not match the original's!";
                    return;
                }
    
                Decrypted = CryptographicEngine.Decrypt(keyPair, Encrypted, null);
    
                if (!CryptographicBuffer.Compare(Decrypted, Data))
                {
                    OutputText.Text += "Decrypted data does not match original!";
                    return;
                }
            }
        }


    13)使用AsymmetricKeyAlgorithmProvider类 支持签名算法
    修改SignAndVerifySignature.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}" Text="Sign and Verify Signature - how to use asymmetric keys for data signature and how to verify the signature with the WinRT APIs."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ComboBox Name="AlgorithmNames" Width="200" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>ECDSA_P256_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>ECDSA_P384_SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>ECDSA_P521_SHA512</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PKCS1_SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PKCS1_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PKCS1_SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PKCS1_SHA512</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PSS_SHA1</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PSS_SHA256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PSS_SHA384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>RSASIGN_PSS_SHA512</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>DSA_SHA1</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <ComboBox Name="KeySizes" Width="100" Margin="5,5,5,5">
                            <ComboBoxItem>
                                <x:String>256</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>384</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>521</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>1024</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>2048</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>3072</x:String>
                            </ComboBoxItem>
                            <ComboBoxItem>
                                <x:String>4096</x:String>
                            </ComboBoxItem>
                        </ComboBox>
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
    public sealed partial class SignAndVerifySignature : Page
        {
            public SignAndVerifySignature()
            {
                this.InitializeComponent();
                AlgorithmNames.SelectedIndex = 0;
                KeySizes.SelectedIndex = 0;
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String algName = AlgorithmNames.SelectionBoxItem.ToString();
                UInt32 KeySize = UInt32.Parse(KeySizes.SelectionBoxItem.ToString());
                OutputText.Text = "";
    
                CryptographicKey keyPair;
                IBuffer blobOfPublicKey;
                IBuffer blobOfKeyPair;
                String cookie = "Refactor";
                IBuffer Data = CryptographicBuffer.ConvertStringToBinary(cookie, BinaryStringEncoding.Utf16BE);
                AsymmetricKeyAlgorithmProvider Algorithm = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(algName);
    
                OutputText.Text += "*** Sample Signature Algorithm\n";
                OutputText.Text += "    Algorithm Name: " + Algorithm.AlgorithmName + "\n";
                OutputText.Text += "    Key Size: " + KeySize + "\n";
    
                try
                {
                    keyPair = Algorithm.CreateKeyPair(KeySize);
                }
                catch (ArgumentException ex)
                {
                    OutputText.Text += ex.Message + "\n";
                    OutputText.Text += "An invalid key size was specified for the given algorithm.";
                    return;
                }
                IBuffer Signature = CryptographicEngine.Sign(keyPair, Data);
                OutputText.Text += "    Data was successfully signed.\n";
    
                blobOfPublicKey = keyPair.ExportPublicKey();
                blobOfKeyPair = keyPair.Export();
                OutputText.Text += "    Key pair was successfully exported.\n";
    
                CryptographicKey keyPublic = Algorithm.ImportPublicKey(blobOfPublicKey);
    
                if (keyPublic.KeySize != keyPair.KeySize)
                {
                    OutputText.Text += "ImportPublicKey failed!  The imported key's size did not match the original's!";
                    return;
                }
                OutputText.Text += "    Public key was successfully imported.\n";
    
                keyPair = Algorithm.ImportKeyPair(blobOfKeyPair);
    
                if (keyPublic.KeySize != keyPair.KeySize)
                {
                    OutputText.Text += "ImportKeyPair failed!  The imported key's size did not match the original's!";
                    return;
                }
                OutputText.Text += "    Key pair was successfully imported.\n";
    
                if (!CryptographicEngine.VerifySignature(keyPublic, Data, Signature))
                {
                    OutputText.Text += "Signature verification failed!";
                    return;
                }
                OutputText.Text += "    Signature was successfully verified.\n";
            }
        }


    14)使用DataProtectionProvider类
    修改AsynchronousDataProtection.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}" Text="Asynchronous Data Protection -protecting and unprotecting data asynchronously using the WinRT APIs."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <TextBox x:Name="tbDescriptor" Width="340" Text="Local=user" Margin="5,5,5,5" />
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class AsynchronousDataProtection : Page
        {
            public AsynchronousDataProtection()
            {
                this.InitializeComponent();
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            public async void SampleDataProtection(String descriptor)
            {
                OutputText.Text += "*** Sample Data Protection for " + descriptor + " ***\n";
    
                DataProtectionProvider Provider = new DataProtectionProvider(descriptor);
                OutputText.Text += "    DataProtectionProvider is Ready\n";
    
                IBuffer data = CryptographicBuffer.GenerateRandom(73);
                OutputText.Text += "    Original Data: " + CryptographicBuffer.EncodeToHexString(data) + "\n";
    
                IBuffer protectedData = await Provider.ProtectAsync(data);
                OutputText.Text += "    Protected Data: " + CryptographicBuffer.EncodeToHexString(protectedData) + "\n";
    
                if (CryptographicBuffer.Compare(data, protectedData))
                {
                    OutputText.Text += "ProtectAsync returned unprotected data";
                    return;
                }
    
                OutputText.Text += "    ProtectAsync succeeded\n";
    
                DataProtectionProvider Provider2 = new DataProtectionProvider();
                IBuffer unprotectedData = await Provider2.UnprotectAsync(protectedData);
    
                if (!CryptographicBuffer.Compare(data, unprotectedData))
                {
                    OutputText.Text += "UnprotectAsync returned invalid data";
                    return;
                }
    
                OutputText.Text += "    Unprotected Data: " + CryptographicBuffer.EncodeToHexString(unprotectedData) + "\n";
                OutputText.Text += "*** Done!\n";
            }
    
            /// <summary>
            /// This is the click handler for the 'Default' button.  You would replace this with your own handler
            /// if you have a button or buttons on this page.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String descriptor = tbDescriptor.Text;
                SampleDataProtection(descriptor);
            }
        }

    修改AsynchronousDataProtectionWithStreams.xaml的xaml

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid x:Name="Input" Grid.Row="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel>
                    <TextBlock TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}" Text="Asynchronous Data Protection with Streams -  how to use the Data Protection Streaming APIs with memory streams."/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <TextBox x:Name="tbDescriptor" Width="340" Text="Local=user" Margin="5,5,5,5" />
                        <Button x:Name="Run" Content="Run" Margin="0,0,10,0" Click="Run_Click"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
    
            <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                <TextBlock Name="OutputText" TextWrapping="Wrap" Style="{StaticResource BodyTextStyle}"/>
            </Grid>
        </Grid>

      修改后台代码:

    View Code
        public sealed partial class AsynchronousDataProtectionWithStreams : Page
        {
            public AsynchronousDataProtectionWithStreams()
            {
                this.InitializeComponent();
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            public async void SampleDataProtectionStream(String descriptor)
            {
                OutputText.Text += "*** Sample Stream Data Protection for " + descriptor + " ***\n";
    
                IBuffer data = CryptographicBuffer.GenerateRandom(10000);
                DataReader reader1, reader2;
                IBuffer buff1, buff2;
    
                DataProtectionProvider Provider = new DataProtectionProvider(descriptor);
                InMemoryRandomAccessStream originalData = new InMemoryRandomAccessStream();
    
                IOutputStream outputStream = originalData.GetOutputStreamAt(0);
                DataWriter writer = new DataWriter(outputStream);
                writer.WriteBuffer(data);
                await writer.StoreAsync();
                await outputStream.FlushAsync();
    
    
                IInputStream source = originalData.GetInputStreamAt(0);
    
                InMemoryRandomAccessStream protectedData = new InMemoryRandomAccessStream();
                IOutputStream dest = protectedData.GetOutputStreamAt(0);
    
                await Provider.ProtectStreamAsync(source, dest);
    
                if (await dest.FlushAsync())
                    OutputText.Text += "    Protected output was successfully flushed\n";
    
    
                reader1 = new DataReader(originalData.GetInputStreamAt(0));
                reader2 = new DataReader(protectedData.GetInputStreamAt(0));
    
                await reader1.LoadAsync((uint)originalData.Size);
                await reader2.LoadAsync((uint)protectedData.Size);
    
                OutputText.Text += "    Size of original stream:  " + originalData.Size + "\n";
                OutputText.Text += "    Size of protected stream:  " + protectedData.Size + "\n";
    
                if (originalData.Size == protectedData.Size)
                {
                    buff1 = reader1.ReadBuffer((uint)originalData.Size);
                    buff2 = reader2.ReadBuffer((uint)protectedData.Size);
                    if (CryptographicBuffer.Compare(buff1, buff2))
                    {
                        OutputText.Text += "ProtectStreamAsync returned unprotected data";
                        return;
                    }
                }
    
                OutputText.Text += "    Stream Compare completed.  Streams did not match.\n";
    
                source = protectedData.GetInputStreamAt(0);
    
                InMemoryRandomAccessStream unprotectedData = new InMemoryRandomAccessStream();
                dest = unprotectedData.GetOutputStreamAt(0);
    
                DataProtectionProvider Provider2 = new DataProtectionProvider();
                await Provider2.UnprotectStreamAsync(source, dest);
    
                if (await dest.FlushAsync())
                    OutputText.Text += "    Unprotected output was successfully flushed\n";
    
                reader1 = new DataReader(originalData.GetInputStreamAt(0));
                reader2 = new DataReader(unprotectedData.GetInputStreamAt(0));
    
                await reader1.LoadAsync((uint)originalData.Size);
                await reader2.LoadAsync((uint)unprotectedData.Size);
    
                OutputText.Text += "    Size of original stream:  " + originalData.Size + "\n";
                OutputText.Text += "    Size of unprotected stream:  " + unprotectedData.Size + "\n";
    
                buff1 = reader1.ReadBuffer((uint)originalData.Size);
                buff2 = reader2.ReadBuffer((uint)unprotectedData.Size);
                if (!CryptographicBuffer.Compare(buff1, buff2))
                {
                    OutputText.Text += "UnrotectStreamAsync did not return expected data";
                    return;
                }
    
                OutputText.Text += "*** Done!\n";
            }
    
    
            private void Run_Click(object sender, RoutedEventArgs e)
            {
                String descriptor = tbDescriptor.Text;
                SampleDataProtectionStream(descriptor);
            }
        }


    未完待续,敬请期待...
    转载请注明出处:http://www.cnblogs.com/refactor/

  • 相关阅读:
    Eclipse 3.7(代号Indigo) 中文字体太小解决办法(转)
    tomcat配置及使用 环境变量设置
    Eclipse启动的时候窗口一闪就关的解决办法(转)
    Jquery datatables 重载数据方法
    手把手教你从 Core Data 迁移到 Realm
    App 启动加载广告页面思路
    iOS 类似美团外卖 app 两个 tableView 联动效果实现
    从 ReactiveCocoa 中能学到什么?不用此库也能学以致用
    几句话实现导航栏透明渐变 – iOS
    谈谈iOS中粘性动画以及果冻效果的实现
  • 原文地址:https://www.cnblogs.com/refactor/p/2552659.html
Copyright © 2011-2022 走看看