Skip to content

Commit 3aa3744

Browse files
committed
feat: new rc6 with w and r
1 parent 1561e82 commit 3aa3744

3 files changed

Lines changed: 577 additions & 121 deletions

File tree

src/core/operations/RC6Decrypt.mjs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Operation from "../Operation.mjs";
88
import Utils from "../Utils.mjs";
99
import OperationError from "../errors/OperationError.mjs";
1010
import { toHex } from "../lib/Hex.mjs";
11-
import { decryptRC6 } from "../lib/RC6.mjs";
11+
import { decryptRC6, getBlockSize, getDefaultRounds } from "../lib/RC6.mjs";
1212

1313
/**
1414
* RC6 Decrypt operation
@@ -23,7 +23,7 @@ class RC6Decrypt extends Operation {
2323

2424
this.name = "RC6 Decrypt";
2525
this.module = "Ciphers";
26-
this.description = "RC6 is a symmetric key block cipher derived from RC5. It was designed by Ron Rivest, Matt Robshaw, Ray Sidney, and Yiqun Lisa Yin to meet the requirements of the AES competition, and was one of the five finalists. RC6 operates on 128-bit blocks and supports key sizes of 128, 192, or 256 bits with 20 rounds.<br><br>When using CBC or ECB mode, the PKCS#7 padding scheme is used.";
26+
this.description = "RC6 is a symmetric key block cipher derived from RC5. It was designed by Ron Rivest, Matt Robshaw, Ray Sidney, and Yiqun Lisa Yin to meet the requirements of the AES competition, and was one of the five finalists.<br><br>RC6 is parameterised as RC6-w/r/b where w is word size in bits (any multiple of 8 from 8-256), r is the number of rounds (1-255), and b is the key length in bytes. The standard AES submission uses w=32, r=20. Common word sizes: 8, 16, 32 (standard), 64, 128.<br><br><b>IV:</b> The Initialisation Vector should be 4*w/8 bytes (e.g. 16 bytes for w=32). If not entered, it will default to null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, the PKCS#7 padding scheme is used.";
2727
this.infoURL = "https://wikipedia.org/wiki/RC6";
2828
this.inputType = "string";
2929
this.outputType = "string";
@@ -59,6 +59,21 @@ class RC6Decrypt extends Operation {
5959
"name": "Padding",
6060
"type": "option",
6161
"value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
62+
},
63+
{
64+
"name": "Word Size",
65+
"type": "number",
66+
"value": 32,
67+
"min": 8,
68+
"max": 256,
69+
"step": 8
70+
},
71+
{
72+
"name": "Rounds",
73+
"type": "number",
74+
"value": 20,
75+
"min": 1,
76+
"max": 255
6277
}
6378
];
6479
}
@@ -71,21 +86,36 @@ class RC6Decrypt extends Operation {
7186
run(input, args) {
7287
const key = Utils.convertToByteArray(args[0].string, args[0].option),
7388
iv = Utils.convertToByteArray(args[1].string, args[1].option),
74-
[,, mode, inputType, outputType, padding] = args;
89+
[,, mode, inputType, outputType, padding, wordSize, rounds] = args;
90+
91+
// Validate word size
92+
if (!Number.isInteger(wordSize) || wordSize < 8 || wordSize > 256 || wordSize % 8 !== 0)
93+
throw new OperationError(`Invalid word size: ${wordSize}. Must be a multiple of 8 between 8 and 256.`);
7594

76-
if (key.length !== 16 && key.length !== 24 && key.length !== 32)
95+
const blockSize = getBlockSize(wordSize);
96+
const defaultRounds = getDefaultRounds(wordSize);
97+
98+
if (key.length === 0)
7799
throw new OperationError(`Invalid key length: ${key.length} bytes
78100
79-
RC6 uses a key length of 16 bytes (128 bits), 24 bytes (192 bits), or 32 bytes (256 bits).`);
101+
RC6 requires a key of at least 1 byte.`);
80102

81-
if (iv.length !== 16 && mode !== "ECB")
103+
if (iv.length !== blockSize && iv.length !== 0 && mode !== "ECB")
82104
throw new OperationError(`Invalid IV length: ${iv.length} bytes
83105
84-
RC6 uses an IV length of 16 bytes (128 bits).
106+
RC6-${wordSize} uses an IV length of ${blockSize} bytes (${blockSize * 8} bits).
85107
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
86108

109+
if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255)
110+
throw new OperationError(`Invalid number of rounds: ${rounds}
111+
112+
Rounds must be an integer between 1 and 255. Standard for w=${wordSize} is ${defaultRounds}.`);
113+
114+
// Default IV to null bytes if empty (like AES)
115+
const actualIv = iv.length === 0 ? new Array(blockSize).fill(0) : iv;
116+
87117
input = Utils.convertToByteArray(input, inputType);
88-
const output = decryptRC6(input, key, iv, mode, padding);
118+
const output = decryptRC6(input, key, actualIv, mode, padding, rounds, wordSize);
89119
return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
90120
}
91121

src/core/operations/RC6Encrypt.mjs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Operation from "../Operation.mjs";
88
import Utils from "../Utils.mjs";
99
import OperationError from "../errors/OperationError.mjs";
1010
import { toHex } from "../lib/Hex.mjs";
11-
import { encryptRC6 } from "../lib/RC6.mjs";
11+
import { encryptRC6, getBlockSize, getDefaultRounds } from "../lib/RC6.mjs";
1212

1313
/**
1414
* RC6 Encrypt operation
@@ -23,7 +23,7 @@ class RC6Encrypt extends Operation {
2323

2424
this.name = "RC6 Encrypt";
2525
this.module = "Ciphers";
26-
this.description = "RC6 is a symmetric key block cipher derived from RC5. It was designed by Ron Rivest, Matt Robshaw, Ray Sidney, and Yiqun Lisa Yin to meet the requirements of the AES competition, and was one of the five finalists. RC6 operates on 128-bit blocks and supports key sizes of 128, 192, or 256 bits with 20 rounds.<br><br>When using CBC or ECB mode, the PKCS#7 padding scheme is used.";
26+
this.description = "RC6 is a symmetric key block cipher derived from RC5. It was designed by Ron Rivest, Matt Robshaw, Ray Sidney, and Yiqun Lisa Yin to meet the requirements of the AES competition, and was one of the five finalists.<br><br>RC6 is parameterised as RC6-w/r/b where w is word size in bits (any multiple of 8 from 8-256), r is the number of rounds (1-255), and b is the key length in bytes. The standard AES submission uses w=32, r=20. Common word sizes: 8, 16, 32 (standard), 64, 128.<br><br><b>IV:</b> The Initialisation Vector should be 4*w/8 bytes (e.g. 16 bytes for w=32). If not entered, it will default to null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, the PKCS#7 padding scheme is used.";
2727
this.infoURL = "https://wikipedia.org/wiki/RC6";
2828
this.inputType = "string";
2929
this.outputType = "string";
@@ -59,6 +59,21 @@ class RC6Encrypt extends Operation {
5959
"name": "Padding",
6060
"type": "option",
6161
"value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
62+
},
63+
{
64+
"name": "Word Size",
65+
"type": "number",
66+
"value": 32,
67+
"min": 8,
68+
"max": 256,
69+
"step": 8
70+
},
71+
{
72+
"name": "Rounds",
73+
"type": "number",
74+
"value": 20,
75+
"min": 1,
76+
"max": 255
6277
}
6378
];
6479
}
@@ -71,21 +86,36 @@ class RC6Encrypt extends Operation {
7186
run(input, args) {
7287
const key = Utils.convertToByteArray(args[0].string, args[0].option),
7388
iv = Utils.convertToByteArray(args[1].string, args[1].option),
74-
[,, mode, inputType, outputType, padding] = args;
89+
[,, mode, inputType, outputType, padding, wordSize, rounds] = args;
90+
91+
// Validate word size
92+
if (!Number.isInteger(wordSize) || wordSize < 8 || wordSize > 256 || wordSize % 8 !== 0)
93+
throw new OperationError(`Invalid word size: ${wordSize}. Must be a multiple of 8 between 8 and 256.`);
7594

76-
if (key.length !== 16 && key.length !== 24 && key.length !== 32)
95+
const blockSize = getBlockSize(wordSize);
96+
const defaultRounds = getDefaultRounds(wordSize);
97+
98+
if (key.length === 0)
7799
throw new OperationError(`Invalid key length: ${key.length} bytes
78100
79-
RC6 uses a key length of 16 bytes (128 bits), 24 bytes (192 bits), or 32 bytes (256 bits).`);
101+
RC6 requires a key of at least 1 byte.`);
80102

81-
if (iv.length !== 16 && mode !== "ECB")
103+
if (iv.length !== blockSize && iv.length !== 0 && mode !== "ECB")
82104
throw new OperationError(`Invalid IV length: ${iv.length} bytes
83105
84-
RC6 uses an IV length of 16 bytes (128 bits).
106+
RC6-${wordSize} uses an IV length of ${blockSize} bytes (${blockSize * 8} bits).
85107
Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
86108

109+
if (!Number.isInteger(rounds) || rounds < 1 || rounds > 255)
110+
throw new OperationError(`Invalid number of rounds: ${rounds}
111+
112+
Rounds must be an integer between 1 and 255. Standard for w=${wordSize} is ${defaultRounds}.`);
113+
114+
// Default IV to null bytes if empty (like AES)
115+
const actualIv = iv.length === 0 ? new Array(blockSize).fill(0) : iv;
116+
87117
input = Utils.convertToByteArray(input, inputType);
88-
const output = encryptRC6(input, key, iv, mode, padding);
118+
const output = encryptRC6(input, key, actualIv, mode, padding, rounds, wordSize);
89119
return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
90120
}
91121

0 commit comments

Comments
 (0)