ฉันเป็นหนึ่งในนักเขียนของกิมลี เรามี 2-tweet (280 chars) ใน C แต่ฉันอยากจะดูว่ามันเล็กแค่ไหน
Gimli ( paper , website ) เป็นความเร็วสูงด้วยการออกแบบการเปลี่ยนรูปแบบการเข้ารหัสลับระดับความปลอดภัยสูงที่จะนำเสนอในการประชุมเกี่ยวกับการเข้ารหัสฮาร์ดแวร์และระบบฝังตัว (CHES) 2017 (25-28 กันยายน)
งาน
ตามปกติ: เพื่อให้การนำ Gimli ไปปฏิบัติใช้ในภาษาที่คุณเลือกได้
มันควรจะสามารถใช้เป็นอินพุต 384 บิต (หรือ 48 ไบต์หรือ 12 int ไม่ได้ลงนาม ... ) และผลตอบแทน (อาจแก้ไขในสถานที่ถ้าคุณใช้ตัวชี้) ผลของ Gimliนำไปใช้กับ 384 บิตเหล่านี้
อนุญาตให้ทำการแปลงอินพุตจากทศนิยมฐานสิบหกฐานแปดหรือฐานสอง
กรณีมุมที่อาจเกิดขึ้น
การเข้ารหัสจำนวนเต็มจะถือว่าเป็น endian น้อย (เช่นสิ่งที่คุณอาจมีอยู่แล้ว)
คุณอาจเปลี่ยนชื่อGimli
เป็นG
แต่จะต้องยังคงเป็นการเรียกใช้ฟังก์ชัน
ใครชนะ?
นี่คือ code-golf ดังนั้นคำตอบที่สั้นที่สุดในหน่วยไบต์ชนะ! ใช้กฎมาตรฐานแน่นอน
การดำเนินการอ้างอิงมีให้ด้านล่าง
บันทึก
มีความกังวลเพิ่มขึ้น:
"เฮ้ก๊วนโปรดใช้โปรแกรมของฉันฟรีในภาษาอื่นดังนั้นฉันไม่จำเป็นต้อง" (ขอบคุณกับ @jstnthms)
คำตอบของฉันมีดังนี้:
ฉันสามารถทำได้ง่ายๆใน Java, C #, JS, Ocaml ... มันสนุกยิ่งกว่า ขณะนี้เรา (ทีม Gimli) ได้นำไปใช้ (และปรับให้เหมาะสม) กับ AVR, Cortex-M0, Cortex-M3 / M4, Neon, SSE, SSE-unrolled, AVX, AVX2, VHDL และ Python3 :)
เกี่ยวกับกิมลี
รัฐ
Gimli ใช้ลำดับของรอบกับสถานะ 384 บิต รัฐเป็นตัวแทนที่ขนานกับมิติ 3 × 4 × 32 หรือเทียบเท่าเป็นเมทริกซ์ 3 × 4 ของคำ 32- บิต
แต่ละรอบเป็นลำดับของการดำเนินการที่สาม:
- เลเยอร์ที่ไม่ใช่เชิงเส้นโดยเฉพาะ 96 บิต SP- กล่องนำไปใช้กับแต่ละคอลัมน์;
- ในทุก ๆ รอบที่สองชั้นผสมเชิงเส้น
- ในทุก ๆ รอบที่สี่
ชั้นที่ไม่ใช่เชิงเส้น
กล่อง SP ประกอบด้วยการทำงานย่อยสามแบบ: การหมุนของคำแรกและคำที่สอง; 3-input non -earear T-function; และการสลับคำแรกและคำที่สาม
ชั้นเชิงเส้น
เลเยอร์เชิงเส้นประกอบด้วยการดำเนินการสลับสองครั้งคือ Small-Swap และ Big-Swap Small-Swap เกิดขึ้นทุก 4 รอบเริ่มจากรอบที่ 1 Big-Swap เกิดขึ้นทุก 4 รอบเริ่มจากรอบที่ 3
ค่าคงที่ทรงกลม
มี 24 รอบในกิมลิหมายเลข 24,23, ... , 1 เมื่อจำนวนรอบ r คือ 24,20,16,12,8,4 เรา XOR ค่าคงที่ของรอบ (0x9e377900 XOR r) เป็นคำแรกของรัฐ
แหล่งอ้างอิงใน C
#include <stdint.h>
uint32_t rotate(uint32_t x, int bits)
{
if (bits == 0) return x;
return (x << bits) | (x >> (32 - bits));
}
extern void gimli(uint32_t *state)
{
int round;
int column;
uint32_t x;
uint32_t y;
uint32_t z;
for (round = 24; round > 0; --round)
{
for (column = 0; column < 4; ++column)
{
x = rotate(state[ column], 24);
y = rotate(state[4 + column], 9);
z = state[8 + column];
state[8 + column] = x ^ (z << 1) ^ ((y&z) << 2);
state[4 + column] = y ^ x ^ ((x|z) << 1);
state[column] = z ^ y ^ ((x&y) << 3);
}
if ((round & 3) == 0) { // small swap: pattern s...s...s... etc.
x = state[0];
state[0] = state[1];
state[1] = x;
x = state[2];
state[2] = state[3];
state[3] = x;
}
if ((round & 3) == 2) { // big swap: pattern ..S...S...S. etc.
x = state[0];
state[0] = state[2];
state[2] = x;
x = state[1];
state[1] = state[3];
state[3] = x;
}
if ((round & 3) == 0) { // add constant: pattern c...c...c... etc.
state[0] ^= (0x9e377900 | round);
}
}
}
รุ่น Tweetable ใน C
นี่อาจไม่ใช่การนำมาใช้ที่เล็กที่สุด แต่เราต้องการมีเวอร์ชันมาตรฐาน C (เช่นไม่มี UB และ "ใช้งานได้" ในไลบรารี)
#include<stdint.h>
#define P(V,W)x=V,V=W,W=x
void gimli(uint32_t*S){for(long r=24,c,x,y,z;r;--r%2?P(*S,S[1+y/2]),P(S[3],S[2-y/2]):0,*S^=y?0:0x9e377901+r)for(c=4;c--;y=r%4)x=S[c]<<24|S[c]>>8,y=S[c+4]<<9|S[c+4]>>23,z=S[c+8],S[c]=z^y^8*(x&y),S[c+4]=y^x^2*(x|z),S[c+8]=x^2*z^4*(y&z);}
ทดสอบเวกเตอร์
อินพุตต่อไปนี้สร้างโดย
for (i = 0;i < 12;++i) x[i] = i * i * i + i * 0x9e3779b9;
และ "พิมพ์" ค่าโดย
for (i = 0;i < 12;++i) {
printf("%08x ",x[i])
if (i % 4 == 3) printf("\n");
}
ดังนั้น:
00000000 9e3779ba 3c6ef37a daa66d46
78dde724 1715611a b54cdb2e 53845566
f1bbcfc8 8ff34a5a 2e2ac522 cc624026
ควรกลับมา:
ba11c85a 91bad119 380ce880 d24c2c68
3eceffea 277a921c 4f73a0bd da5a9cd8
84b673f0 34e52ff7 9e2bef49 f41bb8d6
-round
แทน--round
หมายความว่ามันไม่เคยสิ้นสุด --
อาจไม่แนะนำให้แปลงเป็นเส้นประในรหัส :)