การปิดบัง ID


85

ฉันกำลังมองหาวิธีเข้ารหัส / ทำให้รหัสจำนวนเต็มสับสนเป็นจำนวนเต็มอื่น แม่นยำกว่านั้นฉันต้องการฟังก์ชั่นint F(int x)ดังนั้น

  • x <-> F (x) เป็นการโต้ตอบแบบตัวต่อตัว (ถ้า x! = y, F (x)! = F (y))
  • ให้ F (x) มันง่ายที่จะหา x - ดังนั้น F จึงไม่ใช่ฟังก์ชันแฮช
  • กำหนด x และ F (x) มันยาก / เป็นไปไม่ได้ที่จะหา F (y) บางอย่างเช่นใช้x ^ 0x1234ไม่ได้

เพื่อความชัดเจนฉันไม่ได้มองหาโซลูชันการเข้ารหัสที่แข็งแกร่ง แต่เป็นการทำให้สับสนเท่านั้น ลองนึกภาพโปรแกรมประยุกต์บนเว็บที่มี URL ที่ชอบexample.com/profile/1, example.com/profile/2ฯลฯ โปรไฟล์ตัวเองไม่ได้เป็นความลับ แต่ฉันต้องการที่จะป้องกันไม่ให้ voyeurs สบาย ๆ ไปที่มุมมอง / ดึงข้อมูลโปรไฟล์ทั้งหมดหนึ่งหลังจากที่อื่นดังนั้นผมจึงอยากจะซ่อนอยู่เบื้องหลังพวกเขาสิ่งที่ชอบexample.com/profile/23423, example.com/profile/80980234ฯลฯ แม้ว่า โทเค็นที่จัดเก็บฐานข้อมูลสามารถทำงานได้ค่อนข้างง่ายฉันอยากรู้ว่ามีคณิตศาสตร์ง่ายๆสำหรับสิ่งนี้หรือไม่

หนึ่งในความต้องการที่สำคัญผมไม่ได้ล้างเกี่ยวกับการเป็นว่าผลควรมีลักษณะ "สุ่ม" ที่เป็นที่กำหนดลำดับx,x+1,...,x+n, F(x),F(x+1)...F(x+n)ควรจะได้รูปแบบความคืบหน้าใด ๆ


int F (int x) เป็นข้อกำหนดหรืออาจเป็น int [2] F (int x)?
Eugen Rieck

@Eugen Rieck ฉันอยากให้ x และ F (x) อยู่ในช่วงตัวเลข
georg

@ toon81 ใช่ฟังก์ชันนี้จะถูกเก็บเป็นความลับ
georg

เนื่องจากคุณบอกว่าคุณต้องการไปโดยไม่มีโทเค็นนั่นหมายความว่าคุณต้องการหลีกเลี่ยงตารางการค้นหาแบบใด ๆ หรือไม่?
Daniel Mošmondor

16
ผู้ชายคำถามนี้ถูกระบุไว้อย่างสมบูรณ์และเป็นสิ่งที่ฉันกำลังมองหา งานที่ดี.
Snekse

คำตอบ:


39

ทำให้สับสนด้วยวิธีง่ายๆ 2 หรือ 3 วิธี:

  • XOR
  • สับเปลี่ยนแต่ละบิต
  • แปลงเป็นการแสดงแบบโมดูลาร์ (D.Knuth, Vol.2, Chapter 4.3.2)
  • เลือก 32 (หรือ 64) ชุดย่อยที่ทับซ้อนกันของบิตและ XOR บิตในแต่ละส่วนย่อย (พาริตีบิตของเซตย่อย)
  • แสดงในระบบตัวเลขที่มีความยาวผันแปรและตัวเลขแบบสุ่ม
  • เลือกคู่ของจำนวนเต็มคี่xและyเป็นค่าผกผันที่ทวีคูณซึ่งกันและกัน (โมดูโล 2 32 ) จากนั้นคูณด้วยxเพื่อทำให้สับสนและคูณด้วยyเพื่อคืนค่าการคูณทั้งหมดเป็นโมดูโล 2 32 (ที่มา: "การใช้งานการผกผันการคูณ" โดย Eric เลิศเลิศ )

วิธีระบบตัวเลขความยาวตัวแปรไม่เป็นไปตามข้อกำหนด "ความก้าวหน้า" ของคุณเอง มันก่อให้เกิดความก้าวหน้าทางคณิตศาสตร์สั้น ๆ เสมอ แต่เมื่อรวมกับวิธีอื่นบางอย่างก็ให้ผลลัพธ์ที่ดี

เช่นเดียวกับวิธีการแทนค่าแบบแยกส่วน

นี่คือตัวอย่างโค้ด C ++ สำหรับ 3 วิธีเหล่านี้ ตัวอย่าง Shuffle bits อาจใช้รูปแบบและระยะทางที่แตกต่างกันเพื่อให้ไม่สามารถคาดเดาได้มากขึ้น ตัวอย่างอื่น ๆ อีก 2 ตัวอย่างเหมาะสำหรับคนจำนวนน้อย (เพียงเพื่อให้แนวคิด) ควรขยายเพื่อทำให้ค่าจำนวนเต็มทั้งหมดสับสนอย่างถูกต้อง

// *** Numberic system base: (4, 3, 5) -> (5, 3, 4)
// In real life all the bases multiplied should be near 2^32
unsigned y = x/15 + ((x/5)%3)*4 + (x%5)*12; // obfuscate
unsigned z = y/12 + ((y/4)%3)*5 + (y%4)*15; // restore

// *** Shuffle bits (method used here is described in D.Knuth's vol.4a chapter 7.1.3)
const unsigned mask1 = 0x00550055; const unsigned d1 = 7;
const unsigned mask2 = 0x0000cccc; const unsigned d2 = 14;

// Obfuscate
unsigned t = (x ^ (x >> d1)) & mask1;
unsigned u = x ^ t ^ (t << d1);
t = (u ^ (u  >> d2)) & mask2;
y = u ^ t ^ (t << d2);

// Restore
t = (y ^ (y >> d2)) & mask2;
u = y ^ t ^ (t << d2);
t = (u ^ (u >> d1)) & mask1;
z = u ^ t ^ (t << d1);

// *** Subset parity
t = (x ^ (x >> 1)) & 0x44444444;
u = (x ^ (x << 2)) & 0xcccccccc;
y = ((x & 0x88888888) >> 3) | (t >> 1) | u; // obfuscate

t = ((y & 0x11111111) << 3) | (((y & 0x11111111) << 2) ^ ((y & 0x22222222) << 1));
z = t | ((t >> 2) ^ ((y >> 2) & 0x33333333)); // restore

ขอบคุณสำหรับคำตอบ. หากคุณสามารถให้ตัวอย่างโค้ดหลอกได้ถ้าจะดีมาก
จอร์เจีย

3
@ thg435 ฉันใช้ C ++ แทน pseudocode ไม่ต้องการยกตัวอย่างที่ยังไม่ทดลอง
Evgeny Kluev

1
เมื่อฉันลองใช้รหัสฐานระบบตัวเลขด้านบนด้วย x = 99 ฉันจะได้ z = 44
Harvey

@ ฮาร์วีย์: เพื่อให้ได้ obfuscator แบบย้อนกลับได้ผลิตภัณฑ์ของฐานทั้งหมดควรมีขนาดใหญ่กว่าตัวเลขเพื่อทำให้สับสน ในตัวอย่างนี้ 3 * 4 * 5 = 60 ดังนั้นจำนวนที่มากกว่า (เช่น 99) จะไม่จำเป็นต้องคืนค่าให้เป็นค่าเดียวกัน
Evgeny Kluev

1
@ ฮาร์วีย์: นอกจากนี้ยังเป็นไปได้ที่จะทำให้ผลิตภัณฑ์ของฐานทั้งหมดมีขนาดเล็กลง แต่ใกล้เคียงกับ 2 ^ 32 มากจากนั้นจึงทำให้ค่าที่เหลือสับสนโดยใช้ตารางขนาดเล็ก ในกรณีนี้ทุกอย่างยังคงเป็นตัวเลข 32 บิต
Evgeny Kluev

8

คุณต้องการให้การเปลี่ยนแปลงสามารถย้อนกลับได้และไม่ชัดเจน ฟังดูเหมือนการเข้ารหัสที่รับตัวเลขในช่วงที่กำหนดและสร้างตัวเลขที่แตกต่างกันในช่วงเดียวกัน หากช่วงของคุณเป็นตัวเลข 64 บิตให้ใช้ DES หากช่วงของคุณเป็นตัวเลข 128 บิตให้ใช้ AES หากคุณต้องการช่วงที่แตกต่างกันทางออกที่ดีที่สุดของคุณน่าจะเป็นรหัส Hasty Puddingซึ่งออกแบบมาเพื่อรับมือกับขนาดบล็อกที่แตกต่างกันและด้วยช่วงตัวเลขที่ไม่พอดีกับบล็อกเช่น 100,000 ถึง 999,999


สิ่งที่น่าสนใจ แต่อาจเป็นเรื่องยากที่จะขอให้ใครบางคนใช้การเข้ารหัสที่ 1) ยังไม่ได้รับการทดสอบและ 2) ไม่ได้รับการทดสอบอย่างดีเพราะมันยากที่จะเข้าใจ :)
Maarten Bodewes

ขอบคุณ! ฉันพยายามทำให้มันเรียบง่ายที่สุดเท่าที่จะทำได้
จอร์เจีย

หากคุณไม่พบการใช้งาน Hasty Pudding (คุณต้องการเพียงขนาดที่อนุญาต) คุณสามารถใช้การเข้ารหัส Feistel 4 รอบแบบง่าย ๆ ( en.wikipedia.org/wiki/Feistel_cipher ) ในขนาดบล็อกที่เท่ากัน เพียงแค่เข้ารหัสต่อไปจนกว่าเอาต์พุตจะอยู่ในช่วงที่ถูกต้องเช่นเดียวกับ Hasty Pudding ไม่ปลอดภัย แต่เพียงพอที่จะทำให้สับสน
rossum

NSA ได้เปิดตัวSpeck cipher ซึ่งรวมถึงเวอร์ชันที่มีขนาดบล็อก 32 บิตและ 48 บิต นอกจากนี้ยังอาจเป็นประโยชน์สำหรับการทำให้ตัวเลขสับสนกับขนาดเหล่านั้น โดยเฉพาะอย่างยิ่งเวอร์ชัน 32 บิตน่าจะเป็นประโยชน์
rossum

5

การปิดบังไม่เพียงพอในแง่ของความปลอดภัย

อย่างไรก็ตามหากคุณกำลังพยายามขัดขวางผู้เข้าชมแบบสบาย ๆ ฉันขอแนะนำให้ใช้สองวิธีร่วมกัน:

  • คีย์ส่วนตัวที่คุณรวมกับ id โดย xor'ing เข้าด้วยกัน
  • หมุนบิตตามจำนวนที่กำหนดทั้งก่อนและหลังใช้คีย์

นี่คือตัวอย่าง (โดยใช้รหัสหลอก):

  def F(x)
    x = x XOR 31415927       # XOR x with a secret key
    x = rotl(x, 5)           # rotate the bits left 5 times
    x = x XOR 31415927       # XOR x with a secret key again
    x = rotr(x, 5)           # rotate the bits right 5 times
    x = x XOR 31415927       # XOR x with a secret key again
    return x                 # return the value
  end

ฉันยังไม่ได้ทดสอบ แต่ฉันคิดว่านี่สามารถย้อนกลับได้ควรจะเร็วและไม่ง่ายเกินไปที่จะล้อเลียนวิธีการนี้


นอกจากนี้ยังมีการเพิ่ม mod คงที่ 2 ^ 32 (เนื่องจากการหมุนบิตของคุณทำให้ฉันนึกถึง rot13 ซึ่งเป็นฟังก์ชันย้อนกลับที่ทุกคนชื่นชอบ)
ccoakley

แค่นั้นจริงๆreturn x XOR rotr(31415927, 5)ใช่มั้ย? x ครั้งสุดท้ายหรือเลิกทำอันแรกและการหมุนเลิกทำซึ่งกันและกัน .. แน่นอนว่าห่วงโซ่ของการดำเนินการย้อนกลับใด ๆ ก็ย้อนกลับได้เช่นกันดังนั้นจึงเป็นไปตามเงื่อนไขนั้น
harold

ฉันทำการทดสอบสั้น ๆ สองสามครั้งและพอใจกับผลลัพธ์ที่ได้ตามที่คาด ตามที่ ccoakley กล่าวถึง rot13 สามารถใช้แทน rot5 ได้การหมุนใด ๆ จะทำงาน (ข้อแม้: 0> rot> integer-size) และอาจถือได้ว่าเป็นคีย์อื่น มีสิ่งอื่น ๆ ที่คุณสามารถใส่ลงไปได้ที่นี่เช่นโมดูลัสตามที่เขาแนะนำและตราบใดที่มันย้อนกลับได้ตามที่ฮาโรลด์กล่าวไว้
IAmNaN

1
ขออภัย @harold ส่วนใหญ่จะเป็นที่ถูกต้อง - ฟังก์ชั่นทั้งหมดของคุณจะเทียบเท่ากับx = x XOR F(0)หรือหรือx = x XOR 3087989491 x = x XOR rotr(31415927, 5)xors ตัวแรกและตัวสุดท้ายของคุณจะลบล้างซึ่งกันและกันดังนั้นสิ่งที่คุณทำก็คือการ xoring อินพุตที่ปรับบิตด้วยคีย์ - หรือเทียบเท่ากับ xoring อินพุตด้วยคีย์ที่เพิ่มบิต โปรดทราบว่าสิ่งนี้เป็นจริงแม้ว่าคุณจะใช้คีย์ที่แตกต่างกันสำหรับแต่ละขั้นตอน - คีย์ทั้งหมดสามารถรวมเป็นคีย์เดียวที่สามารถ xored กับข้อความธรรมดาได้
Nick Johnson

2
ที่แย่ไปกว่านั้นมันค่อนข้างง่ายที่จะพิสูจน์ว่าโซ่ใด ๆ ที่หมุนโดยออฟเซ็ตคงที่และ xors ที่มีค่าคงที่สามารถควบแน่นเป็นเพียงการหมุนเพียงครั้งเดียวและ xor เพียงตัวเดียว สามารถหมุนสองครั้งหลังจากแต่ละอันสามารถรวมกันได้ (เพิ่มออฟเซ็ต), xors สองตัวหลังจากแต่ละอันสามารถรวมกันได้ (xor กับ xor ของค่าคงที่ทั้งสอง) และสามารถสลับคู่ xor / rot เป็น rot / xor ได้โดยใช้การหมุนเดียวกันกับ ค่าคงที่ใน xor
harold


3

ฉันเขียนโค้ด JS โดยใช้แนวคิดบางอย่างในเธรดนี้:

const BITS = 32n;
const MAX = 4294967295n;
const COPRIME = 65521n;
const INVERSE = 2166657316n;
const ROT = 6n;
const XOR1 = 10296065n; 
const XOR2 = 2426476569n;


function rotRight(n, bits, size) {
    const mask = (1n << bits) - 1n;
    // console.log('mask',mask.toString(2).padStart(Number(size),'0'));
    const left = n & mask;
    const right = n >> bits;
    return (left << (size - bits)) | right;
}

const pipe = fns => fns.reduce((f, g) => (...args) => g(f(...args)));

function build(...fns) {
    const enc = fns.map(f => Array.isArray(f) ? f[0] : f);
    const dec = fns.map(f => Array.isArray(f) ? f[1] : f).reverse();

    return [
        pipe(enc),
        pipe(dec),
    ]
}

[exports.encode, exports.decode] = build(
    [BigInt, Number],
    [i => (i * COPRIME) % MAX, i => (i * INVERSE) % MAX],
    x => x ^ XOR1,
    [x => rotRight(x, ROT, BITS), x => rotRight(x, BITS-ROT, BITS)],
    x => x ^ XOR2,
);

มันให้ผลลัพธ์ที่ดีเช่น:

1 1352888202n 1 'mdh37u'
2 480471946n 2 '7y26iy'
3 3634587530n 3 '1o3xtoq'
4 2225300362n 4 '10svwqy'
5 1084456843n 5 'hxno97'
6 212040587n 6 '3i8rkb'
7 3366156171n 7 '1jo4eq3'
8 3030610827n 8 '1e4cia3'
9 1889750920n 9 'v93x54'
10 1017334664n 10 'gtp0g8'
11 4171450248n 11 '1wzknm0'
12 2762163080n 12 '19oiqo8'
13 1621319561n 13 'qtai6h'
14 748903305n 14 'cdvlhl'
15 3903018889n 15 '1sjr8nd'
16 3567473545n 16 '1mzzc7d'
17 2426613641n 17 '144qr2h'
18 1554197390n 18 'ppbudq'
19 413345678n 19 '6u3fke'
20 3299025806n 20 '1ik5klq'
21 2158182286n 21 'zoxc3y'
22 1285766031n 22 'l9iff3'
23 144914319n 23 '2ea0lr'
24 4104336271n 24 '1vvm64v'
25 2963476367n 25 '1d0dkzz'
26 2091060108n 26 'ykyob0'
27 950208396n 27 'fpq9ho'
28 3835888524n 28 '1rfsej0'
29 2695045004n 29 '18kk618'
30 1822628749n 30 'u559cd'
31 681777037n 31 'b9wuj1'
32 346231693n 32 '5q4y31'

ทดสอบกับ:

  const {encode,decode} = require('./obfuscate')

  for(let i = 1; i <= 1000; ++i) {
        const j = encode(i);
        const k = decode(j);
        console.log(i, j, k, j.toString(36));
   }

XOR1และXOR2เป็นเพียงตัวเลขสุ่มระหว่าง 0 MAXและ MAXคือ2**32-1; คุณควรตั้งค่านี้เป็นสิ่งที่คุณคิดว่า ID สูงสุดของคุณจะเป็น

COPRIMEเป็นตัวเลขที่มีMAXปัญหาร่วมกัน ฉันคิดว่าจำนวนเฉพาะนั้นมีความสัมพันธ์กันกับจำนวนอื่น ๆ (ยกเว้นตัวคูณของตัวมันเอง)

INVERSEเป็นเรื่องยุ่งยากที่จะคิดออก บล็อกโพสต์เหล่านี้ไม่ได้ให้คำตอบที่ตรง แต่WolframAlpha สามารถหาคำตอบให้คุณได้ โดยทั่วไปเพียงแค่การแก้สมการสำหรับ(COPRIME * x) % MAX = 1x

buildฟังก์ชั่นเป็นสิ่งที่ผมสร้างขึ้นเพื่อให้ง่ายต่อการสร้างการเข้ารหัส / ถอดรหัสท่อเหล่านี้ คุณสามารถป้อนการดำเนินการได้มากเท่าที่คุณต้องการเป็น[encode, decode]คู่ ฟังก์ชันเหล่านี้จะต้องเท่ากันและตรงกันข้าม XORฟังก์ชั่นการชมเชยของตัวเองเพื่อให้คุณไม่จำเป็นต้องมีคู่


นี่เป็นอีกหนึ่งการคิดค้นที่สนุก:

function mixHalves(n) {
    const mask = 2n**12n-1n;
    const right = n & mask;
    const left = n >> 12n;
    const mix = left ^ right;
    return (mix << 12n) | right;
}

(สมมติว่าเป็นจำนวนเต็ม 24 บิต - เพียงแค่เปลี่ยนตัวเลขสำหรับขนาดอื่น ๆ )


1
เจ๋งขอบคุณสำหรับการแบ่งปัน! BTW "32n" คืออะไร? ไม่เคยเห็นแบบนี้มาก่อน
georg

1
nเป็น postfix หมายเลขBigInts เป็นคุณสมบัติ JS ใหม่ที่ช่วยให้คุณประมวลผลตัวเลขจำนวนมากได้ ฉันจำเป็นต้องใช้มันเพราะฉันกำลังคูณด้วยตัวเลขจำนวนมากซึ่งอาจทำให้ค่ากลางค่าหนึ่งเกินชั่วคราวNumber.MAX_SAFE_INTEGERและสูญเสียความแม่นยำไป
mpen

2

ทำอะไรก็ได้กับบิตของ ID ที่จะไม่ทำลายมัน ตัวอย่างเช่น:

  • หมุนค่า
  • ใช้การค้นหาเพื่อแทนที่บางส่วนของค่า
  • xor ด้วยค่าบางส่วน
  • สลับบิต
  • แลกเปลี่ยนไบต์
  • สะท้อนมูลค่าทั้งหมด
  • สะท้อนส่วนหนึ่งของค่า
  • ... ใช้จินตนาการของคุณ

สำหรับการถอดรหัสให้ทำทั้งหมดในลำดับย้อนกลับ

สร้างโปรแกรมที่จะ 'เข้ารหัส' ค่าที่น่าสนใจสำหรับคุณและใส่ไว้ในตารางที่คุณสามารถตรวจสอบได้ มีโปรแกรมเดียวกันทดสอบรูทีนการเข้ารหัส / ถอดรหัสของคุณด้วยชุดค่าทั้งหมดที่คุณต้องการให้มีในระบบของคุณ

เพิ่มสิ่งต่างๆในรายการด้านบนลงในกิจวัตรจนกว่าตัวเลขของคุณจะดูยุ่งเหยิงสำหรับคุณ

สำหรับสิ่งอื่นได้รับสำเนาของหนังสือ


สิ่งที่คุณอธิบายคือส่วนประกอบของการเข้ารหัสบล็อก มันสมเหตุสมผลกว่าที่จะใช้สิ่งที่มีอยู่มากกว่าประดิษฐ์ของคุณเอง
Nick Johnson

@NickJohnson ฉันรู้ว่าคุณคลิกที่ลิงค์ในบรรทัดสุดท้ายของโพสต์ของฉันหรือไม่?
Daniel Mošmondor

ฉันล้มเหลวในการรวบรวมชุดค่าผสม rotl / xor ที่ให้ผลลัพธ์ที่ดู "สุ่ม" เพียงพอ (ดูการอัปเดต) คำแนะนำใด ๆ
จอร์เจีย

@ DanielMošmondorฉันรู้ว่าคุณกำลังเชื่อมโยงกับอะไร - แต่นั่นไม่ได้เปลี่ยนความจริงที่ว่าตอนแรกคุณแนะนำให้เขาสร้างอะไรบางอย่างด้วยตัวเองเมื่อมันสมเหตุสมผลกว่าที่จะใช้สิ่งที่มีอยู่?
Nick Johnson

@NickJohnson เห็นได้ชัดว่า OP ไม่ต้องการใช้ crypto ที่มีอยู่เนื่องจากเขาต้องการเรียนรู้หรือไม่เรียนรู้ API ใหม่ ฉันสามารถเกี่ยวข้องกับสิ่งนั้นได้ทั้งหมด
Daniel Mošmondor

2

ฉันเขียนบทความเกี่ยวกับการเรียงสับเปลี่ยนที่ปลอดภัยด้วยการเข้ารหัสบล็อกซึ่งควรจะเป็นไปตามข้อกำหนดของคุณ

ฉันขอแนะนำว่าหากคุณต้องการตัวระบุที่เดายากคุณควรใช้ตั้งแต่แรก: สร้าง UUID และใช้เป็นคีย์หลักสำหรับระเบียนของคุณตั้งแต่แรก - ไม่จำเป็นต้องสามารถ เพื่อแปลงเป็นและจากรหัส 'จริง'


2
@ thg435 หากคุณสนใจแนวทางนี้ข้อความค้นหาที่มีประโยชน์คือ "Format-Preservation Encryption" หน้าวิกิพีเดียครอบคลุมกระดาษ Black / Rogaway ที่กล่าวถึงในบทความของ Nick รวมถึงพัฒนาการล่าสุด ฉันใช้ FPE สำเร็จสำหรับสิ่งที่คล้ายกับสิ่งที่คุณกำลังทำอยู่ แม้ว่าในกรณีของฉันฉันเพิ่มบิตเล็กน้อยนอกเหนือจากรหัสที่ฉันใช้สำหรับการตรวจสอบความถูกต้องของแสง
Paul Du Bois

1

ไม่แน่ใจว่าต้อง "ยาก" แค่ไหนใช้หน่วยความจำเร็วแค่ไหนหรือน้อยแค่ไหน หากคุณไม่มีข้อ จำกัด ของหน่วยความจำคุณสามารถสร้างรายการจำนวนเต็มทั้งหมดสับเปลี่ยนและใช้รายการนั้นเป็นการแมป อย่างไรก็ตามแม้จะเป็นจำนวนเต็ม 4 ไบต์คุณก็ต้องใช้หน่วยความจำมาก

อย่างไรก็ตามสิ่งนี้สามารถทำให้เล็กลงได้ดังนั้นแทนที่จะทำแผนที่จำนวนเต็มทั้งหมดคุณจะจับคู่ไบต์เพียง 2 (หรือกรณีที่แย่ที่สุด 1) และใช้กับแต่ละกลุ่มในจำนวนเต็ม ดังนั้นการใช้ 2 ไบต์จำนวนเต็มจะเป็น(group1) (group2)คุณจะจับคู่แต่ละกลุ่มผ่านแผนที่แบบสุ่ม แต่นั่นหมายความว่าหากคุณเปลี่ยนเฉพาะ group2 การแมปสำหรับ group1 จะยังคงเหมือนเดิม สิ่งนี้สามารถ "แก้ไข" ได้โดยการจับคู่บิตที่ต่างกันกับแต่ละกลุ่ม

ดังนั้น * (group2) อาจจะ (บิต 14,12,10,8,6,4,2,0) เพื่อให้เพิ่ม 1 จะเปลี่ยนทั้งกลุ่มที่ 1และgroup2

อย่างไรก็ตามนี่เป็นเพียงการรักษาความปลอดภัยโดยการปิดบังใครก็ตามที่สามารถป้อนตัวเลขลงในฟังก์ชันของคุณ (แม้ว่าคุณจะเก็บฟังก์ชันเป็นความลับก็ตาม) ก็สามารถเข้าใจได้อย่างง่ายดาย


ขึ้นอยู่กับข้อ จำกัด ของระบบสิ่งนี้อาจใช้ไม่ได้เพราะถ้าคุณสามารถแปลง F (x) กลับไปเป็น x ได้คุณจะต้องมีการเรียงสับเปลี่ยนที่พร้อมใช้งานซึ่งคุณสามารถคำนวณ F (y) ได้อย่างง่ายดาย y โดยพลการ
templatetypedef

@templatetypedef อย่างที่บอกนี่เป็นเพียงการรักษาความปลอดภัยโดยการปิดบัง การเรียงสับเปลี่ยนจะต้องเป็นที่รู้จัก แต่คุณสามารถเห็นการเรียงสับเปลี่ยนเป็น "คีย์" ปัญหาใหญ่ที่สุดที่นี่คือ OP ดูเหมือนว่าต้องการเข้ารหัสข้อความทั้งหมดในชุดเดียว (อันเล็ก) โดยที่ข้อความที่เข้ารหัสควรอยู่ในชุดเดียวกันและควรใช้ได้กับข้อความทั้งหมดในชุด
Roger Lindsjö

ขอบคุณ. ฉันพยายามหลีกเลี่ยงตารางการค้นหาใด ๆ
จอร์เจีย

1

สร้างคีย์สมมาตรส่วนตัวเพื่อใช้ในแอปพลิเคชันของคุณและเข้ารหัสจำนวนเต็มของคุณด้วย สิ่งนี้จะตอบสนองความต้องการทั้งสามรวมถึงข้อที่ 3 ที่ยากที่สุด: เราจะต้องเดาคีย์ของคุณเพื่อที่จะทำลายโครงการของคุณ


thg435 ขอจำนวนเต็มเป็นจำนวนเต็ม (และเท่าที่ฉันเข้าใจควรใช้ได้กับจำนวนเต็มทั้งหมด) คุณช่วยแนะนำอัลกอริทึมคีย์ส่วนตัวที่มีคุณสมบัติเหล่านี้ได้ไหม
Roger Lindsjö

1

สิ่งที่คุณกำลังอธิบายในที่นี้ดูเหมือนจะตรงข้ามกับฟังก์ชันทางเดียว: มันง่ายที่จะกลับหัว แต่ใช้ยากมาก ทางเลือกหนึ่งคือการใช้อัลกอริธึมการเข้ารหัสคีย์สาธารณะมาตรฐานนอกชั้นวางซึ่งคุณแก้ไขคีย์สาธารณะ (ลับเลือกแบบสุ่ม) ที่คุณเก็บเป็นความลับและคีย์ส่วนตัวที่คุณแชร์กับคนทั้งโลก ด้วยวิธีนี้ฟังก์ชัน F (x) ของคุณจะเป็นการเข้ารหัส x โดยใช้คีย์สาธารณะ จากนั้นคุณสามารถถอดรหัส F (x) กลับไปเป็น x ได้อย่างง่ายดายโดยใช้คีย์การถอดรหัสส่วนตัว โปรดสังเกตว่าบทบาทของคีย์สาธารณะและคีย์ส่วนตัวจะกลับด้านที่นี่ - คุณให้คีย์ส่วนตัวแก่ทุกคนเพื่อให้สามารถถอดรหัสฟังก์ชันได้ แต่เก็บคีย์สาธารณะไว้เป็นความลับบนเซิร์ฟเวอร์ของคุณ ทางนั้น:

  1. ฟังก์ชันนี้เป็น bijection ดังนั้นจึงกลับไม่ได้
  2. เมื่อพิจารณาถึง F (x) x จึงสามารถคำนวณได้อย่างมีประสิทธิภาพ
  3. เมื่อพิจารณาถึง x และ F (x) การคำนวณ F (y) จาก y จึงเป็นเรื่องยากมากเนื่องจากไม่มีคีย์สาธารณะ (สมมติว่าคุณใช้รูปแบบการเข้ารหัสที่เข้มงวดในการเข้ารหัส) ไม่มีวิธีที่เป็นไปได้ในการเข้ารหัสข้อมูลแม้ว่าจะเป็นแบบส่วนตัวก็ตาม คีย์ถอดรหัสเป็นที่รู้จัก

สิ่งนี้มีข้อดีหลายประการ ขั้นแรกคุณสามารถมั่นใจได้ว่าระบบ crypto นั้นปลอดภัยเนื่องจากหากคุณใช้อัลกอริทึมที่มีชื่อเสียงเช่น RSA คุณก็ไม่จำเป็นต้องกังวลกับความไม่ปลอดภัยโดยบังเอิญ ประการที่สองมีไลบรารีอยู่แล้วเพื่อทำสิ่งนี้ดังนั้นคุณไม่จำเป็นต้องเขียนโค้ดมากนักและสามารถป้องกันการโจมตีด้านข้าง สุดท้ายคุณสามารถทำให้ทุกคนไปและกลับค่า F (x) ได้โดยที่ไม่มีใครสามารถคำนวณ F (x) ได้จริง

รายละเอียดอย่างหนึ่ง - คุณไม่ควรใช้ประเภท int มาตรฐานที่นี่ แม้จะมีจำนวนเต็ม 64 บิต แต่ก็มีชุดค่าผสมน้อยมากที่ผู้โจมตีสามารถพยายามย้อนกลับทุกอย่างจนกว่าจะพบการเข้ารหัส F (y) สำหรับ y บางตัวแม้ว่าจะไม่มีคีย์ก็ตาม ฉันขอแนะนำให้ใช้บางอย่างเช่นค่า 512 บิตเนื่องจากแม้แต่การโจมตีแบบนิยายวิทยาศาสตร์ก็ไม่สามารถบังคับสิ่งนี้ได้

หวังว่านี่จะช่วยได้!


แต่ดูเหมือนว่า thg435 จะขอการเข้ารหัสที่สามารถเข้ารหัสชุดข้อความขนาดเล็ก (ข้อความ 4 ไบต์) เป็นชุดข้อความเดียวกันและการเข้ารหัสควรใช้ได้กับทุกข้อความ
Roger Lindsjö

ขอบคุณสำหรับคำตอบ. การใช้กรอบการเข้ารหัสเต็มรูปแบบอาจเป็นวิธีที่ดีที่สุดในการทำเช่นนั้น แต่ก็ "หนัก" เกินไปสำหรับความต้องการของฉัน
จอร์เจีย

1

ถ้าxorเป็นที่ยอมรับสำหรับทุกอย่าง แต่อนุมานF(y)ได้รับxและF(x)จากนั้นฉันคิดว่าคุณสามารถทำเช่นนั้นกับเกลือ ก่อนอื่นให้เลือกฟังก์ชันทางเดียวที่เป็นความลับ ตัวอย่างเช่นS(s) = MD5(secret ^ s). จากนั้นF(x) = (s, S(s) ^ x)ที่sถูกสุ่มเลือก ผมเขียนว่า tuple F(x) = 10000 * s + S(s) ^ xแต่คุณสามารถรวมสองส่วนเป็นจำนวนเต็มเช่น ถอดรหัสสารสกัดจากเกลืออีกครั้งและการใช้งานs F'(F(x)) = S(extract s) ^ (extract S(s)^x)ให้xแล้วF(x)คุณจะเห็นs(แม้ว่าจะสับสนเล็กน้อย) และคุณสามารถอนุมานได้S(s)แต่สำหรับผู้ใช้รายอื่นที่yมีเกลือสุ่มอื่นtที่ผู้ใช้รู้ว่าF(x)ไม่สามารถหาS(t)ได้


ขอบคุณ แต่นี่ดูไม่สุ่มพอสำหรับฉัน (ดูการอัปเดต)
georg

เกลือจะถูกเลือกแบบสุ่มและแฮชS(s)ก็จะมีลักษณะสุ่มดังนั้นF(x)จะไม่มีความก้าวหน้าใด ๆ เลย
Ben Jackson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.