Mật mã máy tính


14

Giới thiệu:

Tôi có vô số mật mã khác nhau được lưu trữ trong một tài liệu tôi từng biên soạn khi còn bé, tôi đã chọn một vài trong số những mật mã mà tôi nghĩ là phù hợp nhất cho các thử thách (không quá tầm thường và không quá khó) và biến chúng thành thử thách. Hầu hết trong số họ vẫn còn trong hộp cát, và tôi không chắc liệu tôi sẽ đăng tất cả chúng hay chỉ một vài. Nhưng đây là người đầu tiên trong số họ bắt đầu mọi thứ.


Mật mã máy tính sẽ mã hóa văn bản đã cho thành các nhóm ký tự 'ngẫu nhiên' của một nhóm nhất định length. Nếu một nhóm như vậy chứa một chữ số, nó sẽ sử dụng chữ số đó để lập chỉ mục thành nhóm riêng cho ký tự được mã hóa. Nếu không có chữ số nào trong nhóm, điều đó có nghĩa là ký tự đầu tiên được sử dụng.

Ví dụ: giả sử chúng tôi muốn mã hóa văn bản this is a computer ciphervới độ dài cho trước 5. Đây là một đầu ra tiềm năng (lưu ý: các số được lập chỉ mục 1 trong ví dụ bên dưới):

t     h     i     s     i     s     a     c     o     m     p     u     t     e     r     c     i     p     h     e     r       (without spaces of course, but added as clarification)
qu5dt hprit k3iqb osyw2 jii2o m5uzs akiwb hwpc4 eoo3j muxer z4lpc 4lsuw 2tsmp eirkr r3rsi b5nvc vid2o dmh5p hrptj oeh2l 4ngrv   (without spaces of course, but added as clarification)

Hãy lấy một vài nhóm làm ví dụ để giải thích cách giải mã nhóm:

  • qu5dt: Nhóm này chứa một chữ số 5, do đó, ký tự thứ 5 (1 chỉ mục) của nhóm này là ký tự được sử dụng cho văn bản được giải mã : t.
  • hprit: Nhóm này không chứa chữ số, do đó, ký tự đầu tiên của nhóm này được sử dụng ngầm cho văn bản được giải mã : h.
  • osyw2: Nhóm này chứa một chữ số 2, do đó, ký tự thứ 2 (1 chỉ mục) của nhóm này là ký tự được sử dụng cho văn bản được giải mã : s.

Thử thách:

Cho một số nguyên lengthvà chuỗi word_to_encipher, xuất ngẫu nhiên chuỗi được mã hóa như được mô tả ở trên.

Bạn chỉ phải mã hóa cho lengthword_to_encipher, do đó không cần phải tạo chương trình / chức năng giải mã. Tuy nhiên, tôi có thể thực hiện một thử thách phần 2 cho việc giải mã trong tương lai.

Quy tắc thử thách:

  • Bạn có thể giả định lengthsẽ nằm trong phạm vi [3,9].
  • Bạn có thể giả sử di word_to_encipherchúc chỉ chứa các chữ cái.
  • Bạn có thể sử dụng cả chữ thường hoặc chữ hoa đầy đủ (vui lòng cho biết cái nào bạn đã sử dụng trong câu trả lời của mình).
  • Đầu ra của bạn, mỗi nhóm và vị trí của các chữ số trong một nhóm (nếu có) phải là ngẫu nhiên thống nhất . Vì vậy, tất cả các chữ cái ngẫu nhiên của bảng chữ cái có cùng cơ hội xảy ra; vị trí của chữ cái được mã hóa trong mỗi nhóm có cùng cơ hội xảy ra; và vị trí của chữ số có cùng cơ hội xảy ra (ngoại trừ khi đó là ký tự đầu tiên và không có chữ số nào xuất hiện; và rõ ràng nó không thể ở cùng vị trí với ký tự được mã hóa).
  • Bạn cũng được phép sử dụng các chữ số 0 được lập chỉ mục thay vì 1 chỉ mục. Vui lòng cho biết câu nào trong hai câu bạn đã sử dụng trong câu trả lời của bạn.
  • Chữ số 1(hoặc 0khi được lập chỉ mục 0) sẽ không bao giờ xuất hiện trong đầu ra. Vì vậy, b1ndhkhông phải là một nhóm hợp lệ để mã hóa ký tự 'b'. Tuy nhiên, b4tbwcó giá trị, nơi 4enciphers sự btại 4 (1-lập chỉ mục) vị trí, và các nhân vật khác b, t, wlà ngẫu nhiên (mà tình cờ cũng chứa một b). Nhóm hợp lệ có thể khác của lengthtừ 5 đến Mã hóa nhân vật 'b' là: abcd2, ab2de, babbk, hue5b,, vv

Quy tắc chung:

  • Đây là , vì vậy câu trả lời ngắn nhất bằng byte thắng.
    Đừng để ngôn ngữ mã-golf ngăn cản bạn đăng câu trả lời với các ngôn ngữ không mã hóa. Cố gắng đưa ra một câu trả lời càng ngắn càng tốt cho ngôn ngữ lập trình 'bất kỳ'.
  • Quy tắc chuẩn áp dụng cho câu trả lời của bạn với quy tắc I / O mặc định , vì vậy bạn được phép sử dụng STDIN / STDOUT, các hàm / phương thức với các tham số thích hợp và kiểu trả về, chương trình đầy đủ. Cuộc gọi của bạn.
  • Lỗ hổng mặc định bị cấm.
  • Nếu có thể, vui lòng thêm một liên kết với một bài kiểm tra cho mã của bạn (ví dụ TIO ).
  • Ngoài ra, thêm một lời giải thích cho câu trả lời của bạn rất được khuyến khích.

Các trường hợp thử nghiệm:

Input:
 Length:           5
 Word to encipher: thisisacomputercipher
Possible output:
 qu5dthpritk3iqbosyw2jii2om5uzsakiwbhwpc4eoo3jmuxerz4lpc4lsuw2tsmpeirkrr3rsib5nvcvid2odmh5phrptjoeh2l4ngrv

Input:
 Length:           8
 Word to encipher: test
Possible output:
 ewetng4o6smptebyo6ontsrbtxten3qk

Input:
 Length:           3
 Word to encipher: three
Possible output:
 tomv3h2rvege3le

2
"Đồng phục" nghĩa là gì
l4m2

@ l4m2 Điều đó có cơ hội như nhau cho bất kỳ đầu ra nào. Vì vậy, tất cả các chữ cái ngẫu nhiên của bảng chữ cái có cùng cơ hội xảy ra; vị trí của chữ cái được mã hóa trong mỗi nhóm có cùng cơ hội xảy ra; và vị trí của chữ số có cùng cơ hội xảy ra (ngoại trừ khi đó là ký tự đầu tiên và không có chữ số nào xuất hiện, và cũng không ở cùng vị trí với ký tự được mã hóa).
Kevin Cruijssen

Vì vậy abcd2, ab2de, babbktất cả giống nhau không? Cũng b1akkhợp lệ?
l4m2

@ l4m2 Yep, cả ba đều là đầu ra có thể mã hóa ký tự 'b'. Đối với b1akktôi muốn nói không. Sẽ chỉnh sửa nó trong mô tả thách thức để làm rõ. Nếu ký tự đầu tiên là ký tự được mã hóa, không có chữ số nào xuất hiện.
Kevin Cruijssen

1
Ví dụ: khi length = 3, char = "a"; Các hình thức "a??"có 676 kết quả tốt, nhưng "1a?", "?a1", "2?a", "?2a", có only104 kết quả. Vì vậy, nếu tôi đang cố chọn một kết quả trong tất cả 780 kết quả này, thì phân phối "vị trí của chữ được mã hóa" là 13: 1: 1, không phải 1: 1: 1. Và tôi sẽ coi đây là cách "ngẫu nhiên thống nhất" hoạt động.
tsh

Câu trả lời:


3

Bình thường, 22 byte

smsXWJOQXmOGQJdO-UQJJz

Hãy thử trực tuyến.

Sử dụng chữ thường và chỉ mục không.

Giải trình

Thuật toán rất đơn giản.

                           Implicit: read word in z
                           Implicit: read number in Q
 m                   z     For each char d in z:
      OQ                     Choose a number 0..Q-1
     J                       and call it J.
         m  Q                Make an array of Q
          OG                 random letters.
        X     d              Place d in this string
             J               at position J.
    W                        If J is not 0,
   X                J        place J in this string
               O             at a random position from
                 UQ          0..Q-1
                -  J         except for J.
  s                          Concatenate the letters.
s                          Concatenate the results.

5

Perl 6 , 125 byte

->\n{*.&{S:g{.}=(65..90)>>.chr.roll(n).join.subst(/./,$/,:th($!=roll 1..n:)).subst(/./,$!,:th($!-1??(^n+1$!).roll!!n+1))}}

Hãy thử trực tuyến!

Đưa đầu vào và đầu ra bằng chữ hoa. Mất đầu vào, như thế f(n)(string). Sử dụng 1 chỉ mục.

Giải trình:

->\n{*.&{ ...  }}   # Anonymous code block that takes a number n and returns a function
     S:g{.}=        # That turns each character of the given string into
                          .roll(n)      # Randomly pick n times with replacement
            (65..90)>>.chr              # From the uppercase alphabet
                                  .join # And join
            .subst(                         ) # Then replace
                   /./,  ,:th($!=roll 1..n:)  # A random index (saving the number in $!)
                       $/               # With the original character
            .subst(                )    # Replace again
                   /./,$!,:th( ... )    # The xth character with $!, where x is:
                           $!-1??          # If $! is not 1
                                 (^n+1$!).roll       # A random index that isn't $!
                                               !!n+1  # Else an index out of range

4

Python 2 , 187 177 176 156 154 148 byte

lambda l,s:''.join([chr(choice(R(65,91))),c,`n`][(j==n)-(j==i)*(n>0)]for c in s for n,i in[sample(R(l),2)]for j in R(l))
from random import*
R=range

Hãy thử trực tuyến!

Sử dụng chữ hoa và số 0 được lập chỉ mục.

-3 byte, nhờ Kevin Cruijssen


@KevinCruijssen Cảm ơn :)
TFeld

sample(R(l),2)[::1|-(random()<.5)]nghĩa là gì?
l4m2

@ l4m2 Phải mất 2 số range(l)và xáo trộn chúng. Nhưng rõ ràng mẫu không đảm bảo trật tự, vì vậy không cần thiết :)
TFeld

Bạn có thể loại bỏ dấu ngoặc đơn xung quanh (j==i)*(n>0)? Bội số có ưu tiên toán tử hơn phép trừ không?
Kevin Cruijssen

1
@KevinCruijssen Vâng, tôi đã quên xóa chúng, khi tôi gặp một số vấn đề
TFeld


3

R , 134 132 123 byte

function(S,n,s=sample)for(k in utf8ToInt(S)){o=k+!1:n
P=s(n,1)
o[-P]=s(c(P[i<-P>1],s(17:42,n-1-i,T)))+48
cat(intToUtf8(o))}

Hãy thử trực tuyến!

Có chữ in hoa.

Giải thích về mã cũ (chủ yếu là cùng một cách tiếp cận):

function(S,n){s=sample				# alias
K=el(strsplit(S,""))				# split to characters
o=1:n						# output array
for(k in K){					# for each character in the string
P=s(n,1)					# pick a Position for that character
o[-P]=						# assign to everywhere besides P:
      s(					# a permutation of:
	c(P[i<-P>1],				# P if it's greater than 1
		s(letters,n-1-i,T)))		# and a random sample, with replacement, of lowercase letters
o[P]=k						# set k to position P
cat(o,sep="")}}					# and print

2

Java (JDK) , 193 byte

s->n->s.flatMap(c->{int a[]=new int[n],i=n,x=0;for(;i-->0;)a[i]+=Math.random()*26+97;a[i+=Math.random()*n+1]=c;x+=Math.random()*~-n;if(i>0)a[x<i?x:x+1]=48+i;return java.util.Arrays.stream(a);})

Hãy thử trực tuyến!

  • Chỉ số này dựa trên 0.
  • Mục này sử dụng một IntStream(thông qua String::chars) làm đầu vào, cũng như một số và trả về một số khác IntStream.
  • Phôi từ doubleđến intlà không cần thiết vì +=hack.

2

Japt , 29 byte

;£=VöJ;CöV hUÎX hUÅÎUÎ?UÎs:Cö

Hãy thử trực tuyến!

Không có chỉ mục.

Giải trình:

;                                :Set C = [a...z]
 £                               :For each character of the input:
  =VöJ;                          : Get two different random indexes from [0,length)
       CöV                       : Get 5 random letters
           hUÎX                  : Replace one at random with the character from the input
                hUÅÎ             : Replace a different random character with:
                    UÎ?          :  If the input character was not placed at 0:
                       UÎs       :   The index of the input character
                          :      :  Otherwise:
                           Cö    :   A random letter
                                 :Implicitly join back to a string

2

C, 115 byte

g(_,n)char*_;{int i=rand(),j=i%~-n,k=0;for(i%=n;k<n;k++)putchar(k-i?!i|i<k^k-j?rand()%26+97:48+i:*_);*++_&&g(_,n);}

Hãy thử trực tuyến!

0-index, chữ thường.

Hơi vô dụng và mở rộng:

g(char*_,int n) {
    int i = rand(), j = i%(n-1), k = 0;
    for(i = i%n; k<n; k++)
        putchar(k!=i ? i!=0 || k==j + (k>i)
                          ? rand()%26 + 'A'
                          : i + '0')
                    : *_);
    if (*++_!=0) g(_,n);
}

Các mã nên khá đơn giản. Hai randoms i, jđược tạo trong một rand()cuộc gọi là độc lập vì gcd ( n, ~-n) = 1 và RAND_MAXlớn.


1
Chào mừng đến với PPCG! :)
Shaggy

1

Sạch sẽ , 256 byte

import StdEnv
s::!Int->Int
s _=code {
ccall time "I:I"
ccall srand "I:I"
}
r::!Int->Int
r _=code {
ccall rand "I:I"
}
$n|s 0<1#k=map\e.r e rem n
=flatten o map\c.hd[map(\i|i==x=c=toChar if(i==y&&x>0)(x+48)(r i rem 26+97))[0..n-1]\\x<-k[0..]&y<-k[0..]|x<>y]

Hãy thử trực tuyến!

Lựa chọn:

  • ngẫu nhiên x(vị trí của nhân vật trong đoạn)
  • ngẫu nhiên y không bằng x(vị trí của chữ số trong đoạn)
  • một chữ cái viết thường ngẫu nhiên cho mỗi vị trí không bằng xvà không bằng ytrừ khi xbằng không

1

JavaScript, 134 byte

l=>w=>w.replace(/./g,c=>eval("for(s=c;!s[l-1]||s[t?t-1||9:0]!=c;t=s.replace(/\\D/g,''))s=(p=Math.random()*36**l,p-p%1).toString(36)"))

Hãy thử trực tuyến!

Câu trả lời này đã chọn chuỗi được mã hóa từ tất cả các chuỗi được mã hóa có thể thống nhất. Vì vậy, có thể làm cho chữ cái được mã hóa là chữ cái đầu tiên.


1

C # (Trình biên dịch tương tác Visual C #) , 171 byte

s=>n=>{var r=new Random();return s.SelectMany(c=>{int i=r.Next(n),j=r.Next(n-1);j+=j<i?0:1;return new int[n].Select((_,k)=>(char)(i==k?c:j==k&i>0?i+49:r.Next(26)+97));});}

Hãy thử trực tuyến!

Giải trình...

// s is the input string
// n is the input length
s=>n=>{
  // we need to create an instance
  // of Random and use throughout
  var r=new Random();
  // iterate over s, each iteration
  // returns an array... flatten it
  return s.SelectMany(c=>{
    // i is the position of the letter
    // j is the position of the number
    int i=r.Next(n), j=r.Next(n-1);
    // ensure i and j are different
    j+=j<i?0:1;
    // create an iterable of size n
    return new int[n]
      // iterate over it with index k
      .Select((_,k)=>(char)(
        // return the letter
        i==k?c:
        // return the number
        j==k&i>0?i+49:
        // return a random letter
        r.Next(26)+97)
      );
  });
}

1

Than , 35 30 byte

NθFS«≔‽θη≔∧η‽Φθ⁻κηζFθ≡κζIηηι‽β

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Chỉ số 0. Giải trình:

Nθ

Nhập chiều dài.

FS«

Nhập từ và lặp qua các ký tự.

≔‽θη

Chọn một vị trí ngẫu nhiên cho chữ cái được giải mã.

≔∧η‽Φθ⁻κηζ

Chọn một vị trí ngẫu nhiên khác nhau cho chữ số, trừ khi chữ cái ở vị trí 0, trong trường hợp đó cũng đặt chữ số ở vị trí 0.

Fθ≡κ

Lặp lại một lần cho mỗi ký tự đầu ra và bật vị trí.

ζIη

Nếu đây là vị trí của chữ số thì xuất ra vị trí của chữ được giải mã.

ηι

Nhưng nếu đây là vị trí của chữ được giải mã thì xuất ra chữ cái. Điều này được ưu tiên hơn vị trí của chữ số vì Char than có mục nhập cuối cùng nếu nhiều trường hợp chuyển đổi có cùng giá trị.

‽β

Nếu không, xuất ra một chữ cái ngẫu nhiên.


0

05AB1E , 26 byte

ε²Ý¨Ω©A.r²£Šǝ®Āi®²Ý¨®KΩǝ]J

Chỉ số 0.

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

ε            # Map over the characters of the first (implicit) input-string:
 ²Ý¨         #  Create a list in the range [0, second input)
    Ω        #  Get a random item from this list
     ©       #  Store it in the register (without popping)
 A           #  Push the lowercase alphabet
  .r         #  Shuffle it
    ²£       #  Leave only the first second input amount of characters
      Š      #  Triple swap, so the stack order becomes:
             #  random index; random string; map-character
       ǝ     #  Insert the map-character at this random index into the random string
 ®Āi         #  If the random index was NOT 0:
    ®        #   Push the random index
    ²Ý¨      #   Push the list in the range [0, second input) again
       ®K    #   Remove the random index from this list
         Ω   #   Get a random item from this list
          ǝ  #   Insert the first random index at the second random index into the string
]            # Close both the if-else and map
 J           # Join all strings together (and output implicitly)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.