वन-टाइम पैड को लागू करें


13

पृष्ठभूमि

एक बार का पैड एन्क्रिप्शन का एक रूप है जिसे अगर सही तरीके से इस्तेमाल किया जाए तो यह असंभव है।

एन्क्रिप्शन एक प्लेटेक्स्ट (केवल अक्षर AZ से मिलकर) और एक ही लंबाई (केवल पत्र भी) पर एक यादृच्छिक स्ट्रिंग उत्पन्न करके किया जाता है। यह स्ट्रिंग कुंजी का काम करती है। प्लेनटेक्स्ट के प्रत्येक कैरेक्टर को तब कुंजी में संबंधित कैरेक्टर के साथ जोड़ा जाता है। सिफरटेक्स्ट की गणना निम्नानुसार की जाती है: प्रत्येक जोड़ी के लिए, दोनों वर्ण संख्याओं (A = 0, B = 1, ... Z = 25) में परिवर्तित हो जाते हैं। दो संख्याओं को जोड़ा जाता है modulo 26. यह संख्या एक वर्ण में परिवर्तित की गई है।

डिक्रिप्शन बिल्कुल विपरीत है। सिफरटेक्स्ट और की के पात्रों को जोड़ा जाता है और संख्याओं में परिवर्तित किया जाता है। कुंजी को तब सिफरटेक्स्ट मोडुलो 26 से घटाया जाता है, और परिणाम वापस एक चरित्र AZ में परिवर्तित हो जाता है।

चुनौती

आपकी चुनौती सबसे कम संभव प्रोग्राम को लिखना है जो एक समय के पैड को एन्क्रिप्ट और डिक्रिप्ट कर सकता है।

इनपुट की पहली पंक्ति (STDIN) पर, "ENCRYPT" शब्द या "DECPTPT" शब्द होगा।

यदि शब्द एन्क्रिप्ट है, तो अगली पंक्ति प्लेनटेक्स्ट होगी। आपके प्रोग्राम को दो लाइनों (STDOUT) को आउटपुट करना चाहिए, पहला कुंजी और दूसरा सिफरटेक्स्ट।

यदि शब्द डिक्रिप्ट है, तो आपके प्रोग्राम को इनपुट की दो और लाइन मिलेंगी। पहली पंक्ति कुंजी होगी, और दूसरी पंक्ति सिफरटेक्स्ट होगी। आपको प्रोग्राम को एक पंक्ति आउटपुट करना चाहिए, जो कि हटाए गए प्लेनटेक्स्ट होगा।

प्लेनटेक्स्ट, सिफरटेक्स्ट और की को हमेशा अपरकेस अक्षर AZ से मिलकर बना होना चाहिए। वे हमेशा एक ही लाइन में रहेंगे और उनमें कोई व्हाट्सएप नहीं होगा।

कुंजी हमेशा यादृच्छिक होनी चाहिए। इसके किसी भी बड़े हिस्से को रनों के बीच दोहराना नहीं चाहिए, और ऐसा कोई पैटर्न नहीं होना चाहिए जो पाठ में पाया जा सके।

दो सरल उदाहरण:

ENCRYPT
HAPPYBIRTHDAY
>ABKJAQLRJESMG
>HBZYYRTICLVME

DECRYPT
ABKJAQLRJESMG
HBZYYRTICLVME
>HAPPYBIRTHDAY

>का प्रतिनिधित्व करता है जो लाइनों, उत्पादन कर रहे हैं ताकि आप आउटपुट के रूप में है कि प्रतीक मुद्रित करने के लिए नहीं है।


7
यह स्वयं की योग्यता (जो ठीक है) पर चुनौती की आलोचना करने के लिए नहीं है, लेकिन मैं यहां क्रिप्टोग्राफी की आलोचना करने जा रहा हूं । आप जो वर्णन कर रहे हैं वह एक "स्ट्रीम सिफर" है क्योंकि यह एक PRNG पर निर्भर करता है (जब तक कि आपके कंप्यूटर को किसी स्रोत या वास्तविक यादृच्छिकता तक नहीं पहुंचता है (और अगर / dev / urandom की गिनती का linux कार्यान्वयन कुछ बहस का विषय है)), और महत्वपूर्ण समय पर विकसित होने के कारण ओटीपी के लिए एकमात्र अच्छा उपयोग पराजित होता है जो सुरक्षित संचार का समय परिवर्तन है।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

1
साथ ही, सभी चुनौतियां डिफ़ॉल्ट रूप से भाषा अज्ञेय हैं, इसलिए मैंने वह टैग हटा दिया है।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली

7
@dmckee आपकी पहली टिप्पणी के बारे में, मैं सहमत हूं, यही कारण है कि मैं अपने संचार को सुरक्षित करने के लिए इन उत्तरों का उपयोग करने का इरादा नहीं करता हूं।
फीनोटपी

1
यह समस्या से यादृच्छिकता छोड़ने के लिए और अधिक मजेदार IMO होता; यादृच्छिकता का स्रोत दिया गया ( /dev/random, haveged), बाइट्स के साथ ऑर्डर्स को एन्क्रिप्ट करके और उन्हें कुंजी के साथ एक्सरे करके डिक्रिप्ट करें। gist.github.com/5078264 कुंजी या यादृच्छिकता को स्टडिन से पढ़ा जा सकता है, संदेश या साइबरफोर्ट एक फ़ाइल नाम तर्क हो सकता है।
ixtmixilix 20

@PhiNotPi मेरा एक सुझाव है। अगर वे वास्तव में यादृच्छिक स्रोत (जैसे /dev/hwrng, छद्म यादृच्छिक का उपयोग करने के बजाय (जो तकनीकी रूप से इसे बनाता है तो टूट जाता है।) का उपयोग करके बोनस नहीं देते हैं ।
PyRulez

जवाबों:


8

गोल्फस्क्रिप्ट, 53 वर्ण

n%(0=2%{~.,[{26rand 65+}*]:K]}*zip{{-}*~)26%65+}%K]n*

यह एक ऐसा कार्य है जिसके लिए गोल्फस्क्रिप्ट अभी पूरी तरह से अनुकूल है।

कोड को छोटा रखने के लिए, मैं एन्क्रिप्शन और डिक्रिप्शन दोनों के लिए समान कोड का उपयोग कर रहा हूं: डिक्रिप्ट करने के लिए, मैं सिफरटेक्स्ट से कुंजी को हटाता हूं, जबकि एन्क्रिप्शन के लिए, मैं पहले एक यादृच्छिक सिफरटेक्स्ट उत्पन्न करता हूं और फिर प्लेनटेक्स्ट को इसमें से घटाता हूं। फिर भी, एन्क्रिप्शन मोड को लागू करने के लिए अतिरिक्त कोड प्रोग्राम की आधी लंबाई से थोड़ा अधिक लेता है।

टिप्पणियों के साथ डी-गोल्फ संस्करण:

n %             # split input into an array of lines

# KEY GENERATION FOR ENCRYPTION MODE:
(               # extract the first line from the array
0 = 2 %         # check if the first char of that line is odd (E = 69)...
{               # ...and execute this block if it is:
    ~           # dump the remaining lines (of which the should be only one) on the stack
    . ,         # calculate the length of the last line...
    [ { 26 rand 65 + } * ]  # ...make an array of that many random letters...
    :K          # ...and assign it to K
    ]           # collect all the lines, including K, back into an array
} *

# ENCRYPTION / DECRYPTION ROUTINE:
zip             # transpose the array of 2 n-char strings into n 2-char strings...
{               # ...and execute this block for each 2-char string:
    {-} *       # subtract the second char code from the first
    ~ )         # negate the result (using the two's complement trick -x = ~x+1)
    26 % 65 +   # reduce modulo 26 and add 65 = A
} %

# OUTPUT:
K ] n*         # join the result and K (if defined) with a newline, stringifying them

4

रूबी ( 200 185)

नमूना रन + wc:

$ ruby onetimepad.rb
ENCODE
ANOTHERTESTINPUTZZZ
ZYCLGHDWLDASFUTHWKC
BPMIBXOXTPTQIVBMDPX
$ ruby onetimepad.rb
DECODE
ZYCLGHDWLDASFUTHWKC
BPMIBXOXTPTQIVBMDPX
ANOTHERTESTINPUTZZZ
$ wc onetimepad.rb
       4       7     185 onetimepad.rb
def f;gets.scan(/./).map{|b|b.ord-65};end
s=->a{a.map{|b|(b+65).chr}*''}
r=->b,a,o{s[a.zip(b).map{|a,b|(a.send o,b)%26}]}
puts(gets=~/^D/?r[f,f,:+]:[s[k=(p=f).map{rand 26}],r[k,p,:-]])

s[k=(p=f).map{rand 26}],r[k,p,:-]लिखा जाना चाहिएs[k=f.map{rand 26}],r[k,$_,:-]
हौलेथ

@ कोई भी काम नहीं करता है, जैसा $_कि केवल अंतिम पंक्ति द्वारा पढ़ा जाता है gets। एक लाइन पढ़ने के बाद fभी करता है .scan(/./).map{|b|b.ord-65}
jsvnm

3

हास्केल, 203 वर्ण

import Random
main=newStdGen>>=interact.(unlines.).(.lines).f.randomRs('A','Z')
f k['E':_,x]=[z const k x,z(e(+))k x]
f _[_,k,x]=[z(e(-))k x]
e(%)k x=toEnum$65+o x%o k`mod`26
o c=fromEnum c-65;z=zipWith

उदाहरण:

$ runghc OneTimePad.hs <<< $'ENCRYPT\nHELLOWORLD'
QMNQKGFZFD
XQYBYCTQQG
$ runghc OneTimePad.hs <<< $'DECRYPT\nQMNQKGFZFD\nXQYBYCTQQG'
HELLOWORLD

3

पर्ल, 220 171 वर्ण

if(<>=~/D/){$_=<>;$w=<>;print chr((ord(substr$w,$i++,1)-ord$1)%26+65)while/(.)/g}else{$_=<>;$c.=chr((ord($1)-65+($i=rand(26)))%26+65),print chr$i+65while/(.)/g;print$/.$c}

नमूना रन:

ENCRYPT
HELLO
CCTKK
JGEVY

DECRYPT
CCTKK
JGEVY
HELLO

नोट: कम से कम जब मैं इसे चलाता हूं, तो "जारी रखने के लिए कोई भी कुंजी दबाएं ..." अंतिम आउटपुट के अंत में जोड़ा जाता है। मुझे उम्मीद है कि यह ठीक है, क्योंकि यह कार्यक्रम का हिस्सा नहीं है। यदि नहीं, तो मैं इसे बना सकता हूं ताकि यह अगली पंक्ति में दिखाई दे।

यह पर्ल में मेरा पहला वास्तविक कार्यक्रम है, और मेरा पहला गोल्फ कभी, इसलिए मैं वास्तव में सुझावों की सराहना करूंगा। इसके अलावा, मैंने /(.)/gइंटरनेट पर पाया , लेकिन मुझे नहीं पता कि यह कैसे काम करता है (क्या यह एक नियमित अभिव्यक्ति है? मैंने अभी तक उन लोगों को नहीं सीखा है)। क्या कोई मुझे समझा सकता है?

संपादित करें: मुझे इल्जामियों के साथ मदद करने के लिए इल्मरी करोनन का धन्यवाद, मैंने 7 पात्रों को बचाने के लिए अपने नए ज्ञान का इस्तेमाल किया!

विस्तारित, थोड़ा सुपाठ्य संस्करण:

if(<>=~/D/){
    $_=<>;
    $w=<>;
    print chr((ord(substr$w,$i++,1)-ord$1)%26+65)while/(.)/g
}
else{
    $_=<>;
    $c.=chr((ord($1)-65+($i=rand(26)))%26+65),print chr$i+65while/(.)/g;
    print$/.$c
}

हाँ, /(.)/gएक regexp है। आप निश्चित रूप से उन लोगों को सीखना चाहते हैं यदि आप पर्ल गोल्फ खेलने जा रहे हैं। perldoc.perl.org/perlre.html एक बुरी शुरुआत नहीं है।
इल्मरी करोनें

2

पायथन - 304 295

import random
r=raw_input
R=lambda s:range(len(s))
o=lambda c:ord(c)-65
j=''.join
if r()[0]=='D':
 s=r()
 d=r()
 print j(chr((o(s[i])-o(d[i]))%26+65)for i in R(s))
else:
 s=r()
 d=[random.randint(0,26)for i in R(s)]
 print j(chr((o(s[i])+d[i])%26+65)for i in R(s))
 print j(chr(n+65)for n in d)

मेरा मानना ​​है कि यह बिल्कुल चश्मे से मिलता है ( '>'इनपुट प्रॉम्प्ट की शुरुआत में शामिल है ।) यह इनपुट को मान्य नहीं करता है, इसलिए मुझे लगता है कि यह कचरा उत्पादन का उत्पादन करेगा यदि आप इसे वर्णों के बाहर देते हैं [A-Z]। यह केवल इनपुट कमांड के पहले अक्षर की जांच करता है। कुछ के साथ शुरू करने से Dएक डिक्रिप्शन और कुछ और सब पर एक एन्क्रिप्शन में परिणाम होगा।


मुझे उम्मीद नहीं थी कि आप इसे प्रिंट कर सकते हैं >, मैं इसका उपयोग यह दिखाने के लिए कर रहा था कि कौन सी लाइनें आउटपुट थीं। आपको उन पर अमल नहीं करना है।
फीनोटपी

ठीक है, शांत, 9 कम वर्ण तब।
गॉर्डन बैली

1

सी ++ - 220 241 वर्ण, 4 लाइनें

#include<cstdlib>
#include<cstdio>
#define a scanf("%s"
char i,s[99],t[99];int main(){a,t);a,s);if(t[0]>68){for(;s[i];++i)s[i]=(s[i]+(t[i]=rand()%26+65))%26+65;puts(t);}else for(a,t);s[i];++i){s[i]=65+t[i]-s[i];if(s[i]<65)s[i]+=26;}puts(s);}

संपादित करें 1- एमएसवीएस मानक पुस्तकालय में बहुत सारी अनावश्यक फाइलें शामिल हैं, जिसका मतलब है कि ios में वे सभी शामिल हैं जिनकी मुझे आवश्यकता थी लेकिन यह अन्य संकलक के साथ काम नहीं करता था। वास्तविक फ़ाइलों के लिए परिवर्तित आईओएस जो कि आवश्यक कार्य cstdlib और cstdio में दिखाई देते हैं। इसे इंगित करने के लिए इल्मरी करोनन का धन्यवाद।


मेरे लिए संकलित नहीं करता: g++ otp.cppकहता हैotp.cpp: In function ‘int main()’: otp.cpp:3: error: ‘scanf’ was not declared in this scope otp.cpp:3: error: ‘rand’ was not declared in this scope otp.cpp:3: error: ‘puts’ was not declared in this scope otp.cpp:3: error: ‘puts’ was not declared in this scope
इल्मरी करोनें

हुह, यह अजीब है, मैं दृश्य स्टूडियो का उपयोग करता हूं। इसमें <ios> के लिए <conio.h> और <stdio.h> शामिल होना गैर-मानक होना चाहिए। मैंने माना कि हेडर हमेशा अलग-अलग कार्यान्वयन पर एक ही फाइल को शामिल करते हैं। मैं इसे बाद में देखूंगा, धन्यवाद।
स्कॉट लोगन

1

अजगर - २th०

import random
i=raw_input  
m=i()
a=i()
r=range(len(a))
o=ord
j=''.join
if m=='ENCRYPT':
  k=j(chr(65+random.randint(0,25)) for x in r)
  R=k+"\n"+j(chr((o(a[x])+o(k[x]))%26+65) for x in r)
elif m=='DECRYPT':
  k=i()
  R=j(chr((o(k[x])-o(a[x]))%26+65) for x in r)
print R

नमूना उत्पादन:

$ python onetimepad.py 
ENCRYPT
HELLOWORLD
UXCYNPXNNV
BBNJBLLEYY
$ python onetimepad.py 
DECRYPT
UXCYNPXNNV
BBNJBLLEYY
HELLOWORLD

अक्षर गणना:

$ wc -c onetimepad.py 
270 onetimepad.py

1

जे: 94 बाइट्स

3 :0]1
c=:(26&|@)(&.(65-~a.&i.))
r=:1!:1@1:
((],:+c)[:u:65+[:?26$~#)@r`(r-c r)@.('D'={.)r 1
)

सभी आवश्यक सफेद स्थान गिने।

टिप्पणी संस्करण:

3 :0]1                                          NB. Make a function and call it
c=:(26&|@)(&.(65-~a.&i.))                       NB. Adverb for operating on the alphabet
                                                NB. (used for adding and subtracting the pad)
r=:1!:1@1:                                      NB. Read input line and decide (right to left)
((],:+c)[:u:65+[:?26$~#)@r   ` (r-c r)            @. ('D'={.)r 1
NB. Encryption (ger    0)    | Decryption (ger 1)| Agenda               
NB. pad,:(crypt=:plain + pad)| crypt - pad       | If D is first input, do (ger 1), else do (ger 0)
)

1

C # ( 445 416)

एग्रीगेट के बारे में भूल गए। एक अच्छा सा काट लें।

थोड़ा गोल्फ:

namespace G {
using System;
using System.Linq;
using x = System.Console;
class P {
    static void Main() {
        string p = "", c = "", k = "";
        Random r = new Random();
        int i = 0;
        if (x.ReadLine()[0] == 'E') {
            p = x.ReadLine();
            k=p.Aggregate(k,(l,_)=>l+(char)r.Next(65,90));
            c=p.Aggregate(c,(m,l)=>m+(char)((l+k[i++])%26+65));
            x.WriteLine(k + "\n" + c);
        } else {
            k = x.ReadLine();
            c = x.ReadLine();
            p=c.Aggregate(p,(l,a)=>l+(char)((a-k[i++]+26)%26+65));
            x.WriteLine(p);
        }
    }
}

}

golfed:

namespace G{using System;using System.Linq;using x=System.Console;class P{static void Main(){string p="",c="",k="";Random r=new Random();int i=0;if (x.ReadLine()[0]=='E'){p=x.ReadLine();k=p.Aggregate(k,(l,_)=>l+(char)r.Next(65,90));c=p.Aggregate(c,(m,l)=>m+(char)((l+k[i++])%26+65));x.WriteLine(k+"\n"+c);}else{k=x.ReadLine();c=x.ReadLine();p=c.Aggregate(p,(l,a)=>l+(char)((a-k[i++]+26)%26+65));x.WriteLine(p);}}}}

0

सी (159 + 11 संकलक झंडे के लिए)

golfed:

d(a,b){return(a+b+26)%26+65;}a;char s[999],b,*c=s-1;main(){g;a=*s-69;g;while(*++c)a?b=-*c,*c=getchar():putchar(b=rand()%26+65),*c=d(*c,b);a||puts("");puts(s);}

Ungolfed:

d(a,b){
    //*a = (*a + b - 2*65 + 26) % 26 + 65; 
    return (a + b + 26) % 26 + 65;
}
a; char s[999], b, *c = s-1;
main(){
    gets(s);
    a = *s - 69; // -1 if decrypt 0 if encrypt
    gets(s);
    while(*++c){
        if(!a)
            putchar(b = rand() % 26 + 65); // 'A'
        else
            b = -*c, *c = getchar();
        *c = d(*c,b);
    }
    if(!a) puts("");
    puts(s);
}

के साथ संकलित करें -Dg=gets(s)

उदाहरण:

$./onetimepad
ENCRYPT
FOOBAR
>PHQGHU
>UVEHHL
$./onetimepad
DECRYPT
PHQGHU
UVEHHL
>FOOBAR

मुझे हर बार इसे चलाने के लिए एक ही कुंजी मिलती है - कोई यादृच्छिकता नहीं है।
feersum

0

जावास्क्रिप्ट 239

var F=String.fromCharCode
function R(l){var k='';while(l--)k+=F(~~(Math.random()*26)+65);return k}
function X(s,k,d){var o='',i=0,a,b,c
while(i<s.length)a=s.charCodeAt(i)-65,b=k.charCodeAt(i++)-65,c=d?26+(a-b):a+b,o+=F((c%26)+65)
return o}

उपयोग:

var str = "HELLOWORLD";
var key = R(str.length);
var enc = X(str, key, false);
console.log(enc);
console.log(X(enc,key, true));

0

रूबी - 184 179 177 वर्ण

def g;gets.scan(/./).map{|c|c.ord-65}end
m,=g
k=(s=g).map{rand 26}
m==4?(puts k.map{|c|(c+65).chr}*'';y=:+):(k,s=s,g)
puts s.zip(k).map{|c,o|(c.send(y||:-,o).to_i%26+65).chr}*''

इसे इस तरह चलाएं: $ ruby pad-lock.rb

यदि कोई दिलचस्पी रखता है तो यह अनगुल्ड संस्करण है (हालांकि यह गोल्फ वाले के साथ आज तक नहीं है)

def prompt
    gets.scan(/./).map{ |c|c.ord - 65 }
end

mode = prompt[0]
operator = :-
secret = prompt
key = secret.map { |char| rand(26) }

if mode == 4 # the letter E, or ENCRYPT
    key.map { |char| print (char + 65).chr }
    puts
    operator = :+
else
    # make the old secret the new key,
    # and get a new secret (that has been encrypted)
    key, secret = secret, prompt
end

chars = secret.zip(key).map do |secret_char, key_char|

    # if mode == 4 (E) then add, otherwise subtract
    i = secret_char.send(operator, key_char).to_i

    ((i % 26) + 65).chr
end

puts chars.join("")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.