Underhanded Password Hashing [kapalı]


33

Underhanded C Yarışması ruhuyla, Underhanded Code Yarışması başlatıyorum. Bu yarışmanın amacı, basitçe bazı kodları uygulamaktır, aynı zamanda incelikli bir hatayı saklıyor.

Yarışma

Bir Amerikan casus ajansının BT bölümünde çalışan gizli bir Rus köstebesisiniz. Amerikalı patronunuz az önce gizli mesajları şifrelemek için bir şifre toplama algoritması uygulamanızı istedi.

Patronunuz aşağıdaki işlevi uygulamanızı istiyor:

f: String -> byte[16]

bir parolayı AES anahtarı olarak kullanıma uygun 16 baytlık bir miktara dönüştürür. Patronunuz güvenli bir fonksiyon istiyor, bu bağlamda farklı parola dizgilerinin ezici olasılıkla farklı sonuçlar üretmesi gerektiği anlamına geliyor. Örneğin , girişin md5 değerini döndürmek basit bir uygulama olacaktır f.

Elbette , Rus casus ajansındaki asıl patronun bu süreci altüst etmeni isterdi. Göreviniz f, Rusların geri döndürdüğü anahtarları kullanarak şifrelenmiş tüm gizli mesajların şifresini çözebilecek şekilde uygulamaktır f.

Bunu yapmak için, f2 ^ 128 olası çıkışların yalnızca küçük bir alt kümesini döndürecek şekilde uygulamanız gerekir . Özellikle, fen fazla 2 ^ 16 farklı sonuç vermelisiniz , böylece Rusların şifresini çözmek istedikleri şifreli her mesaj için doğru anahtarı bulmak için kolay bir kaba kuvvet araması yapabilirsiniz.

Ancak, casusluğun ölüm cezasını taşıdığını unutmayın. Yakalanmamak için, işleviniz fen az 2 ^ 8 farklı sonuç üretmelidir, böylece bir kaç çıktının bir denetimsel incelemesi fbir kopyasını ortaya çıkarması olası değildir. Ve en önemlisi, menzili sınırlandırmak için girdiğiniz kod fkasıtlı değil, istenmeyen görünmelidir. Eğer bir mahkemeye çekilirseniz, hatayı kasten mi yoksa kazara mı kullandığınızla ilgili makul bir şüpheniz olmalıdır.

yargılamak

Ben ve işe aldığım diğer iki kişi bu girişleri değerlendirecek (değerlendirmek istiyorsanız bana e-posta ile gönderiniz). Kazanan giriş için 200 itibar ödülü teklif ediyorum. Gönderiler 1 Mayıs'a kadar yüklenmelidir.

Yargılama aşağıdaki kriterleri dikkate alacaktır:

  • fSpesifikasyona uyuyor mu , yani 2 ^ 8 ve 2 ^ 16 olası çıkışlar üretiyor mu? Bunların zor sınırlar olduğunu düşünmeyin, ancak menziliniz dışındaysanız puanları düşeriz.
  • Böcek, kasten istemeden yapılan bir hatanın sonucu mu?
  • fGörünüşün çıktıları rastgele görünüyor mu?
  • Uygulamanız ne kadar kısa folursa, o kadar iyidir.
  • Uygulamanız ne kadar net folursa, o kadar iyidir.

notlar

Kodunuzu uygulamak için herhangi bir dili kullanabilirsiniz. Görüşte bir hatayı gizlemeye çalışıyorsunuz, bu yüzden karışık kod önerilmiyor.

İyi bir sunum yapan şey hakkında bir fikir edinmek için önceki Underhanded C yarışmasının kazananlarından bazılarına bakmak isteyebilirsiniz .

Giriş dizeleri basılabilir (32 - 126, dahil) olacaktır. İsterseniz makul bir maksimum uzunluk kabul edebilirsiniz.


1
dizgisinde herhangi bir sınırlama var mı? Sadece alfabeden ibaret mi?
Ali1S232

@Gajet: Tüm yazdırılabilir ascii karakterlerini kullanmalısınız (32 - 126, dahil).
Keith Randall

Çıktı aralığı 16 baytlık dizelerin tümü veya yalnızca yazdırılabilir olanları mı?
Mart’ta stand 20

@ boothby: tüm olası 16 bayt değerler (2 ^ 128 olasılık)
Keith Randall

1
Bu soruyu konu dışı olarak kapatmak için oy veriyorum, çünkü bu konudaki aşikar zorluklar artık konu dışı. meta.codegolf.stackexchange.com/a/8326/20469
kedi

Yanıtlar:


15

C

2 ^ 16 olası çıkışlar (veya kullanılan karakter sayısının 2 ^ 8 katı).
Linux'un MD5 uygulamasını kullanır, yani, AFAIK, sorun değil. Ancak bu, örneğin "40" ve "42" için aynı hastayı verir.
DÜZENLEME: yeniden adlandırıldı bcopyiçin memcpy(tabii takas parametrelerine).
EDIT: Gereksinimleri daha iyi karşılamak için programdan fonksiyona dönüştürülür.

#include <string.h>
#include <openssl/md5.h>

void f(const unsigned char *input, unsigned char output[16]) {

    /* Put the input in a 32-byte buffer, padded with zeros. */
    unsigned char workbuf[32] = {0};
    strncpy(workbuf, input, sizeof(workbuf));

    unsigned char res[MD5_DIGEST_LENGTH];
    MD5(workbuf, sizeof(workbuf), res);

    /* NOTE: MD5 has known weaknesses, so using it isn't 100% secure.
     * To compensate, prefix the input buffer with its own MD5, and hash again. */
    memcpy(workbuf+1, workbuf, sizeof(workbuf)-1);
    workbuf[0] = res[0];
    MD5(workbuf, sizeof(workbuf), res);

    /* Copy the result to the output buffer */
    memcpy(output, res, 16);
}

/* Some operating systems don't have memcpy(), so include a simple implementation */
void *
memcpy(void *_dest, const void *_src, size_t n)
{
    const unsigned char *src = _src;
    unsigned char *dest = _dest;
    while (n--) *dest++ = *src++;
    return _dest;
}

Bu MD5 ile bir kusur mu?
Ali1S232

@Gajet, Hayır, Linux'un MD5'i kullandım, ki bu tamamen iyi (AFAIK).
ugoren

neden daha olası çıktılar üretmiyorlar?
Ali1S232

1
@Gajet: bcopyAdımda ne olduğunu düşünün ... asıl BSD bcopyişlevi burada düzgün bir şekilde çalışacağından , yanlış bir yönlendirme .
Han

@ han, Aslında, şimdi görüyorum ki arabam buçuk bcopy. Bunu değiştireceğim memcpyve aynı uygulama geçerli olacak.
ugoren

13

C

Bu, en ateşli yarışma girişi olmayabilir, ancak sanırım aşağıdakiler, herhangi bir kodlayıcı tarafından kendi iyiliği için çok akıllıca yapılmış, hash fonksiyonlarında gördüğünüz işlemlerin belli belirsiz bir fikri ile yapılmış olan hash fonksiyonunun türü olduğunu düşünüyorum:

#include <stdio.h>
#include <string.h>
#include <stdint.h>

void hash(const char* s, uint8_t* r, size_t n)
{
     uint32_t h = 123456789UL;
     for (size_t i = 0; i < n; i++) {
          for (const char* p = s; *p; p++) {
               h = h * 33 + *p;
          }
          *r++ = (h >> 3) & 0xff;
          h = h ^ 987654321UL;
     }
}

int main()
{
     size_t n = 1024;
     char s[n];
     size_t m = 16;
     uint8_t b[m];
     while (fgets(s, n, stdin)) {
          hash(s, b, m);
          for (size_t i = 0; i < m; ++i)
               printf("%02x", b[i]);
          printf("\n");
     }
}

Aslında, karma işlevi L * 2048'den farklı sonuç veremez, burada L oluşabilecek farklı girdi dizgisi uzunluklarının sayısıdır. Uygulamada kodu, dizüstü bilgisayarımdaki manuel sayfalardan ve html belgelerinden gelen 1.85 milyon benzersiz giriş satırında test ettim ve yalnızca 85428 farklı benzersiz karma elde ettim.


0

Scala:

// smaller values for more easy tests:
val len = 16
// make a 16 bytes fingerprint
def to16Bytes (l: BigInt, pos: Int=len) : List[Byte] = 
  if (pos == 1) List (l.toByte) else (l % 256L).toByte :: to16Bytes (l / 256L, pos-1)
/** if number isn't prime, take next */
def nextProbPrime (l: BigInt) : BigInt = 
  if (l.isProbablePrime (9)) l else nextProbPrime (l + 1)
/** Take every input, shift and add, but take primes */
def codify (s: String): BigInt = 
  (BigInt (17) /: s) ((a, b) => nextProbPrime (a * BigInt (257) + b))
/** very, very short Strings - less than 14 bytes - have to be filled, to obscure them a bit: */
def f (s: String) : Array [Byte] = {
  val filled = (if (s.size < 14) s + "secret" + s else s)
  to16Bytes (codify (filled + filled.reverse)).toArray.map (l => nextProbPrime (l).toByte) 
}

Sonuç, benzer girdi için benzer görünmüyorsa test edin:

val samples = List ("a", "aa", "b", "", "longer example", "This is a foolish, fishy test") 

samples.map (f) 

 List[Array[Byte]] = List(
Array (-41, -113, -79, 127, 29, 127, 31, 67, -19, 83, -73, -31, -101, -113, 97, -113), 
Array (-19, 7, -43, 89, -97, -113, 47, -53, -113, -127, -31, -113, -67, -23, 127, 127), 
Array (-41, -113, -79, 127, 29, 127, 31, 67, -19, 83, -73, -31, -101, -113, 97, -113), 
Array (37, -19, -7, 67, -83, 89, 59, -11, -23, -47, 97, 83, 19, 2, 2, 2), 
Array (79, 101, -47, -103, 47, -13, 29, -37, -83, -3, -37, 59, 127, 97, -43, -43), 
Array (37, 53, -43, -73, -67, 5, 11, -89, -37, -103, 107, 97, 37, -71, 59, 67))

Hata, kodlama için sadece primerleri kullanıyor. Yerine

scala> math.pow (256, 16)
res5: Double = 3.4028236692093846E38

değerleri ile biter

scala> math.pow (54, 16)
res6: Double = 5.227573613485917E27

Çünkü 256'nın altında 54 prime vardır.


2
5.22e27 >> 2^16. Bu kadar çok olasılığın kaba kuvvetini kullanmanın yolu yok.
Keith Randall

dilin ismini unuttun
ajax333221

@ ajax333221: Scala. Zirveye ekledim.
kullanıcı bilinmeyen

@KeithRandall: 'yanlışlıkla' sadece pozitif Byte'leri kullanabilirim, bu da matematik olasılıklarını azaltabilir (27, 16), ama bu hala yaklaşık 8e22.
kullanıcı bilinmeyen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.