RSA oraz faktoryzacja klucza 768 bitowego

Dopiero dzisiaj przypadkiem napotkałem na dokument przedstawiający łamanie klucza 768 bitowego. Zainteresowanych odsyłam tu.

Nie jest to żaden przełom ponieważ w praktyce stosuje się 1024 bitowe klucze, które są znacznie trudniejsze w złamaniu(jak to zresztą podkreślają autorzy powyższej pracy). Wiadomość stanowi raczej ciekawostkę.  Z drugiej strony jednak, rozwój technologiczny prawdopodobnie w przeciągu 1-2 dekad pozwoli łamać 1024 bitowe klucze i konieczne okaże się wykorzystywanie kluczy 2048 bitowych.

Autorzy(m.in. Microsoft Research) eksperymentu wykorzystali klaster do złamania klucza. Dla porównania korzystając z jednordzeniowego procesora 2.2ghz operacja trwałaby 1500 lat. Nadal jedynym sposobem na złamanie klucza są metody wywodzące się z brute-force, więc na dzień dzisiejszy RSA jest wciąż bezpiecznym algorytmem.

Metody częściowe(partial methods)

Z klasami częściowymi większość programistów c# prawdopodobnie miała już styczność. Klasycznym przykładem jest rozbicie klasy Form na część wygenerowaną przez Visual Studio oraz na część przeznaczoną do modyfikacji przez programistę. Metody częściowe są bardzo podobnym mechanizmem. W skrócie są to metody, które można definiować w dwóch różnych plikach. Zdecydowałem się o nich napisać ponieważ wydaje mi się, że są mniej znane, a czasami mogą okazać się przydatne.

Sama deklaracja jest analogiczna do klas częściowym. W jednym pliku deklarujemy metodę:

// Plik A
partial void Method();

W drugim pliku możemy zdefiniować ciało metody:

// Plik B
partial void Method()
{
    MessageBox.Show("Metoda czesciowa");
}

Mechanizm pozwala nam na definicję metody w innym pliku niż jej deklaracja. Metody częściowe mają jedną wyróżniającą cechę – wszelkie wywołania są usuwane na etapie kompilacji w przypadku gdy programista nie zdefiniował ciała tej metody. Dzięki temu kod jest optymalny ponieważ w sytuacji gdy nie było potrzeby definiowania metody, wszelkie wywołania będą usuwane w czasie kompilacji, co skutkuje, że plik końcowy nie będzie zawierał żadnych śladów tej metody.

Metody częściowe najczęściej wykorzystuje się w generatorach kodu. W takim przypadku nie chcemy aby użytkownik kodu modyfikował kod automatycznie wygenerowany(mogło by to zakłócić poprawne działanie tworzonego narzędzia programistycznego). Z drugiej jednak strony, chcemy aby użytkownik mógł modyfikować w jakimś stopniu działanie klasy. Możemy więc zdefiniować pewne metody częściowe, które będą wywoływane w odpowiednich momentach. Użytkownik klasy chcąc wpłynąć na działanie klasy mógłby definiować ciała metod częściowych. Oczywiście podobny rezultat można osiągnąć poprzez dziedziczenie i metody wirtualne, jednak metody częściowe są znacznie bardziej optymalne i przeważnie łatwiejsze w użyciu. Wszystko zależy jednak od konkretnego przypadku użycia – metody częściowe stanowią dodatek a nie próbę zastąpienia dotychczasowych rozwiązań.

BusyIndicator w Silverlight

W Silverlight toolkit można znaleźć bardzo przydatną kontrolkę – BusyIndicator(poprzednia nazwa Activity). Służy ona do zasygnalizowania użytkownikowi, że jakaś operacja jest wykonywana. Na początek screen z gotowej aplikacji:

image

Co warto podkreślić, podczas stanu aktywnego kontrolki użytkownik nie może modyfikować danych, które przedstawia interfejs. Kontrolka działa w trybie modalnym – wszystko w tle jest zablokowane i automatycznie przyciemnione.

Po zainstalowaniu bibliotek z Silverlight toolkit, najlepiej dodać je do toolbox’a . W tym celu klikamy prawym przyciskiem myszki na oknie toolbox a następnie wybieramy “Choose Items”. W oknie przechodzimy do “Silverlight components” i klikamy w przycisk “Browse”. Przechodzimy do katalogu z zainstalowanymi bibliotekami  a następnie zaznaczamy System.Windows.Controls.Toolkit.dll.

Użycie kontrolki sprowadza się do ustawienia właściwości IsBusy na true w przypadku gdy chcemy zasygnalizować użytkownik wykonywaną operację:

<controlsToolkit:BusyIndicator IsBusy="True">

</controlsToolkit:BusyIndicator>

W praktyce oczywiście będziemy korzystać z wiązania danych i jako wartość IsBusy podamy np. {Binding Path=IsBusy}.

Następną istotną sprawą jest fakt, że w kontrolce BusyIndicator możemy zagnieżdżać inne kontrolki, które korzystają ze źródła danych. Wtedy IsBusy przeważnie jest już ustawiane automatycznie przez zagnieżdżoną kontrolkę.

Wygląd i zachowanie BusyIndictator możemy zmieniać dowolnie – podobnie jak resztę kontrolek WPF.

Ustawienie “Culture” w WPF

WPF mam jedną niedogodność – domyślnie wszelkie ustawienia regionalne interfejsu są ustawione na en-US. Oznacza to, że wszystkie domyślne konwertery również korzystają z ustawień en-US. Chcąc wyświetlić np. datę, prawdopodobnie pożądanym będzie przedstawienie daty polskiemu użytkownikowi w formacie dd-mm-yyyy oraz amerykańskiemu w mm-dd-yyyy. Niestety domyślnie właściwość UIElement::Language jest ustawiona na en-US.  Za pomocą prostego kodu możemy jednak zmienić metadane i ustawić prawidłową “kulturę”:

protected override void OnStartup(StartupEventArgs e)
{
    FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(System.Threading.Thread.CurrentThread.CurrentCulture.IetfLanguageTag)));
    
    base.OnStartup(e);
}

Ustawienie prawidłowych ustawień regionalnych najlepiej umieścić w OnStartup ponieważ wystarczy to wykonać tylko raz – przy starcie aplikacji.

IntTextBox oraz RealTextBox w WPF

Poprawnie zaprojektowana aplikacja powinna weryfikować dane w każdej warstwie systemu. Oczywiście najważniejszym miejscem jest warstwa biznesowa ale dobrym zwyczajem jest walidacja również w warstwie prezentacji. W idealnym interfejsie użytkownik nie jest w stanie wprowadzić błędnych danych. Podstawowym przykładem są pola edycyjne w których powinno się wpisać np. ilość sprzedanego produktu. Użytkownik nie powinien mieć możliwości wprowadzenia tekstu w takie pole.

Zacznijmy od prostej sprawy – akceptacja tylko cyfr.

public class IntNumberTextBox:System.Windows.Controls.TextBox
{
    protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = !ValidateText(e.Text);
        base.OnPreviewTextInput(e);
    } 
    private bool ValidateText(string text)
    {
        foreach (Char character in text)
        {
            if (System.Char.IsDigit(character) == false)
                return false;
        }
        return true;
    }
}

Jak widać wystarczy tylko przeładować metodę OnPreviewTextInput i ustawić flagę Handled na true w przypadku gdy wprowadzony znak jest niedozwolony.

W przypadku liczb rzeczywistych musimy umożliwić dodatkowo wprowadzanie przecinków lub kropek. Znak oddzielający część dziesiętną od całkowitej zależy od ustawień regionalnych w systemie operacyjnym. W C# możemy sprawdzić jaki to jest znak za pomocą właściwości System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator.

public class RealNumberTextBox:System.Windows.Controls.TextBox
{
   protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
   {
       e.Handled = !ValidateText(e.Text);
       base.OnPreviewTextInput(e);
   }
   private bool ValidateText(string text)
   {
       if ( text == System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
                  return true;
       foreach (Char character in text)
       {
           if (System.Char.IsDigit(character) == false)
               return false;
       }
       return true;
   }
}

Inne ciekawe wartości, zależne od ustawień regionalnych, które są przydatne w walidacji to m.in CurrencyDecimalSeparator, CurrencyGroupSeparator, CurrencySymbol, NegativeSign, NegativeInfinitySymbol.

Teraz pozostało nam tylko wykorzystać nowo utworzoną kontrolkę w pliku XAML. Najpierw należy zadeklarować przestrzeń nazw:

<Window x:Class="Sample.Views.Product.Product"
        xmlns:controls="clr-namespace:Sampple.Controls"
        inne deklaracje
>

Następnie korzystamy z kontrolki w sposób analogiczny do standardowych kontrolek:

<controls:IntNumberTextBox HorizontalAlignment="Left" Width="200" Text="tekst" />

Pamiętajmy, że walidacja w dolnych warstwach jest zwykle wolniejsza ponieważ należy połączyć się najpierw np. z bazą danych lub z usługą sieciową. Ponadto korzystanie z aplikacji z walidacją w warstwie prezentacji jest po prostu łatwiejsze dla użytkownika.

Filtrowanie QueryString za pomocą maksymalnej długości

IIS 7.0 ze względu bezpieczeństwa ogranicza długość tzw. QueryString do 2048 bajtów. Czasami okazuje się, że długość jest zbyt ograniczająca i nie da się wykonać pewnych operacji takich jak np. przekazanie tokena, który zwykle zajmuje więcej niż naniesione ograniczenie. Na szczęście w pliku konfiguracyjnym web.config można łatwo ustawić dowolną maksymalną długość QueryString:

<system.webServer>
    <security>
        <requestFiltering>        
            <requestLimits maxQueryString="5000" />        
        </requestFiltering>    
    </security>
</system.webServer>

Dobrą zasadą jest również ustawianie długości jak najmniejszej, tak aby wystarczała tylko na przewidziane przypadki użycia.

Prawidłowe zwalnianie zasobów

W języku c# obiekt, którego zasobami chcemy sami zarządzać, powinien implementować interfejs IDisposable. Sporo osób aby zwolnić zasoby pisze następujący kod:

public class MyClass : IDisposable
{
   #region IDisposable Members

   public void Dispose()
   {
       // zwalnianie zasobow
   }

   #endregion
}

Interfejs niestety wymusza nam tylko implementację metody Dispose. Powyższe rozwiązanie jest zdecydowanie nieprawidłowe. Zanim  jednak przejdę do omawia co w kodzie jest niepoprawnego, podam prawidłową implementację:

public class MyClass:IDisposable
{
    private bool IsDisposed=false;
    public void Dispose()
    {
        Dispose(true);
        GC.SupressFinalize(this);
    }
    protected void Dispose(bool Diposing)
    {
        if(!IsDisposed)
        {
            if(Disposing)
            {
                // zwalniaj zasoby zarządzalne
            }
            // zwalniaj zasoby niezarządzalne
        }
        IsDisposed=true;
    }
    ~MyClass()
    {
        Dispose(false);
    }
}

Powyższa implementacja gwarantuje nam, że gdy obiekt będzie automatycznie czyszczony przez GarbageCollector to zasoby niezarządzane i tak zostaną wyczyszczone. Uzyskujemy to dzięki implementacji destruktora, który wywołuje się zawsze gdy GC zwalnia obiekt.  Właśnie w przypadku gdy to GC zwalnia obiekt a nie użytkownik ręcznie, metoda Dispose nie jest wywoływana więc jedynym miejscem na zrobienie tego jest destruktor.

Następna kwestia to przypadek gdy to sam użytkownik chce zwolnić obiekt. W tym przypadku musimy poinformować GC, że bierzemy na siebie odpowiedzialność za obiekt(metoda SupressFinalize) i tym samym destruktor nie zostanie wywołany(co uchroni nas przed zapętleniem).

Ponadto dodałem flagę IsDisposed, która umożliwia nam np. wyrzucenie wyjątku w przypadku gdy użytkownik drugi raz chce zwolnić obiekt.

Wymuszenie walidacji kontrolek w WPF

Windows Presentation Foundation posiada nowy model walidacji kontrolek. Każdej kontrolce podlegającej walidacji przypisujemy zestaw reguł walidacyjnych, np:

<TextBox  Height="23" Margin="120,6,177,0"  VerticalAlignment="Top" >
    <Binding Path="FirstName" Mode="TwoWay">
        <Binding.ValidationRules>
            <DataErrorValidationRule></DataErrorValidationRule>
        </Binding.ValidationRules>
    </Binding>
</TextBox>

Powyższa reguła mówi, że wykorzystywany obiekt biznesowy wspiera interfejs IDataErrorInfo:

public partial class Person : IDataErrorInfo
{
   private Dictionary<string, string> m_ValidationErrors = new Dictionary<string, string>();
   public Invoice()
   {       
   }
   private void AddError(string columnName, string msg)
   {
       if (!m_ValidationErrors.ContainsKey(columnName))
       {
           m_ValidationErrors.Add(columnName, msg);
       }
   }
   private void RemoveError(string columnName)
   {
       if (m_ValidationErrors.ContainsKey(columnName))
       {
           m_ValidationErrors.Remove(columnName);
       }
   }
   partial void OnFirstNameChanged()
   {
       if (string.IsNullOrEmpty(ReceiverName))
       {
           AddError("FirstName", "Musisz podac imie");
       }
       else
           RemoveError("FirstName");
   }
   
   #region IDataErrorInfo Members

   public string Error
   {
       get
       {
           if (m_ValidationErrors.Count > 0)
           {
               return m_ValidationErrors.ElementAt(0).Value;
           }
           else return null;
       }
   }
   public string this[string columnName]
   {
       get
       {
           if (m_ValidationErrors.ContainsKey(columnName))
           {
               return m_ValidationErrors[columnName];
           }
           else return null;
       }
   }
   #endregion
}

W przykładzie wykorzystałem obiekt Entity Framework. Implementacje wymusza nam interfejs więc myślę, że kod nie wymaga dodatkowego komentarza(jeśli macie jakieś pytania to proszę zadawać je np. w komentarzach).

Inna regułą, która spełnia się gdy zostanie wyjątek wyrzucony podczas próby zmiany właściwości jest ExceptionValidationRule. Ponadto, istnieje możliwość definiowania własnych reguł. Gdy któraś kontrolka nie przejdzie walidacji zostaje domyślnie podświetlona na czerwono:

image

Walidacja zostanie jednak wywoływana pierwszy raz w momencie gdy kontrolka straci focus bądź gdy zostanie zmieniona w niej wartość(zależy to od ustawień bindingu). Co jednak w przypadku gdy chcemy aby przy starcie okna błędnie wypełnione pola(w tym przykładzie puste) zostały zaznaczone na czerwono?

Rozwiązanie jest proste: Wystarczy obsłużyć zdarzenie Windows Loaded oraz wykonać poniższy kod:

m_FirstName.GetBindingExpression(TextBox.TextProperty).UpdateSource();

Po wykonaniu kodu, wszystkie puste pola(czyli te, które nie przeszły walidacji) będą podświetlone i tym samym użytkownik będzie wiedział co należy wypełnić.

Jak dostać się do InnerException w RIA Services

Dziś postanowiłem wyjaśnić problem, który zauważyłem jest często poruszany na forach. Załóżmy, że wywołujemy metodę SubmitChanges aby zatwierdzić wprowadzone modyfikacje. Wykonanie metody jednak nie powodzi się i wyrzucany jest wyjątek. Scenariusz wygląda typowo jednak często otrzymujemy mało mówiący komunikat typu:

Submit operation failed. Exception has been thrown by the target of an invocation.

lub

Submit operation failed. An error occurred while updating the entries. See the InnerException for details.

Co gorsza, jeśli zajrzymy do InnerException zobaczymy wartość NULL. Oczywiście mówimy ciągle o stronie klienta. Pytanie brzmi więc: W jaki sposób możemy podejrzeć co tak naprawdę stało się?

Rozwiązaniem jest przeładowanie metody Submit(DomainService) lub OnError(DomainService) oraz obsłużenie tam ewentualnych wyjątków:

public override bool Submit(ChangeSet changeSet)
{
  try
  {
      return base.Submit(changeSet);
  }
  catch (Exception e)
  {
      throw;
  }
}

Jeśli zajrzymy do InnerException zobaczymy, że wyjątek jest tam zapisany i możemy przeczytać dokładniejszą informację np.

Violation of PRIMARY KEY constraint 'PK_Table.Tests'. Cannot insert duplicate key in object 'TestModule.Tests'.
The statement has been terminated.

Rozwiązanie jest być może niezbyt eleganckie ale działa bez zarzutu.

Aktualizacja interfejsu z drugiego wątku(windows forms i WPF)

Na różnych forach często użytkownicy mają problem z aktualizacją kontrolek z innego wątku. Załóżmy, że odpaliliśmy sobie BackgroundWorker lub po prostu Thread. Wykonujemy jakieś operację, np. łączymy się ze zdalnymi zasobami. Stworzenie osobnego wątku w takim scenariuszu jest bardzo pożądane ponieważ nie blokujemy wtedy aktualizacji interfejsu. W trakcie pobierania informacji z Internetu chcemy aktualizować interfejs aby informować użytkownika o postępach np.

progressBar.Value = progessValue;

Jeśli powyższy kod jest wywołany z obcego wątku użytkownik dostanie następujący komunikat o błędzie:

Cross-thread operation not valid:
Control accessed from a thread other than the thread it was created on.

Wyjątek jest wyrzucany ponieważ zarówno w WindowsForms jak i w WPF nie można aktualizować interfejsu z innego wątku niż z tego w którym została stworzona kontrolka. Musimy więc w jakiś sposób dostać się do wątku macierzystego dla kontrolki i tam wykonać aktualizacje tej kontrolki. Służy do tego metoda Control.Invoke(windows forms) lub ControlDispatcher.Invoke(Wpf). Chcąc więc zaktualizować ProgressBar w WinForms musimy napisać:

Action<int> updateAction = new Action<int>((value) => progressBar.Value = value);
progressBar.Invoke(updateAction,32);

Powyższy kod będzie działał w każdym przypadku ale ma jedną wadę związaną z wydajnością kodu. Co w przypadku gdy mamy osobną klasę do aktualizacji interfejsu i jest ona wywoływana zarówno z wątku kontrolki jak i z obcego wątku? Dla drugiego przypadku(z obcego wątku) kod jest maksymalnie optymalny. Z kolei w sytuacji gdy wywołujemy ją z wątku macierzystego dla kontrolki nie potrzebnie będzie wykonywana masa operacji związanych z wpompowaniem operacji w kolejkę dla wątku interfejsu. Na szczęście istnieje gotowa metoda, która stwierdza czy dla aktualnego przypadku użycia jest wymagane wywołanie Invoke:

Action<int> updateAction = new Action<int>((value) => progressBar.Value = value);
if (progressBar.InvokeRequired)
    progressBar.Invoke(updateAction,5);
else
    updateAction(4);

Posiadamy już optymalną wersje kodu. Jednak pisanie powyższego kodu za każdym razem gdy chcemy zaktualizować interfejs(nigdy nie wiemy czy kod nie będzie wywoływany w przyszłości z innego wątku) jest co najmniej niewygodne. Z ratunkiem przychodzą nam tzw. rozszerzenia(extensions,c# 3.0). Możemy przecież stworzyć własną metodę nazwaną powiedzmy InvokeIfRequired:

public static class ControlExtensions
{
   public static void InvokeIfRequired(this Control control, Action action)
   {
       if (control.InvokeRequired)
           control.Invoke(action);
       else
           action();
   }
   public static void InvokeIfRequired<T>(this Control control, Action<T> action, T parameter)
   {
       if (control.InvokeRequired)
           control.Invoke(action, parameter);
       else
           action(parameter);
   }
}

Za pomocą takiego rozwiązania aktualizacja kontrolki sprowadzi się wyłącznie do poniższego kodu:

this.InvokeIfRequired((value) => progressBar.Value = value, 10);

W przypadku Wpf rozwiązanie jest bardzo podobne:

public static class ControlExtensions
{
   public static void InvokeIfRequired(this Control control, Action action)
   {
       if (System.Threading.Thread.CurrentThread!=control.Dispatcher.Thread)
           control.Dispatcher.Invoke(action);
       else
           action();
   }
   public static void InvokeIfRequired<T>(this Control control, Action<T> action, T parameter)
   {
       if (System.Threading.Thread.CurrentThread!=control.Dispatcher.Thread)
           control.Dispatcher.Invoke(action, parameter);
       else
           action(parameter);
   }
}

Z kolei użycie metody jest identyczne jak w przypadku WinForms:

this.InvokeIfRequired((value) => bar.Value = value, 10);