Joseph Haugh
University of New Mexico
struct Point {
int x;
int y;
};
void movePoint(struct Point p, int dx, int dy) {
p.x += dx;
p.y += dy;
}
void main() {
struct Point p = {1, 2};
printf("Before move: (%d, %d)\n", p.x, p.y);
movePoint(p, 3, 4);
printf("After move: (%d, %d)\n", p.x, p.y);
}
Before move: (1, 2)
After move: (1, 2)
struct Rectangle {
int length;
int width;
};
void doubleSize(struct Rectangle *r) {
r->length *= 2;
r->width *= 2;
}
void main() {
struct Rectangle r = {5, 3};
printf("Before doubling: %d x %d\n", r.length, r.width);
doubleSize(&r);
printf("After doubling: %d x %d\n", r.length, r.width);
}
Before doubling: 5 x 3
After doubling: 10 x 6
struct Rectangle {
int length;
int width;
};
struct Rectangle addRects(struct Rectangle r1, struct Rectangle r2) {
struct Rectangle r = { r1.length, r1. width };
r.length += r2.length;
r.width += r2.width;
return r;
}
void main() {
struct Rectangle r1 = {5, 3};
struct Rectangle r2 = {4, 6};
struct Rectangle r3 = addRects(r1, r2);
printf("r3.length = %d, r3.width = %d\n", r3.length, r3.width);
}
r3.length = 9, r3.width = 9
struct Rectangle {
int length;
int width;
};
struct Rectangle *addRects(struct Rectangle r1, struct Rectangle r2) {
struct Rectangle r = { r1.length, r1. width };
r.length += r2.length;
r.width += r2.width;
return &r;
}
void main() {
struct Rectangle r1 = {5, 3};
struct Rectangle r2 = {4, 6};
struct Rectangle *r3 = addRects(r1, r2);
printf("r3.length = %d, r3.width = %d\n", r3->length, r3->width);
}
Segmentation fault (core dumped)
void main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr;
*(ptr++) += 5;
*(++ptr) += 10;
ptr[2] += 15;
printf("%d %d %d %d %d\n",
arr[0], arr[1], arr[2], arr[3], arr[4]);
}
15 20 40 40 65
void main() {
int a = 10;
int *p = &a;
int **q = &p;
**q = 20;
*q = NULL;
printf("a = %d\n", a);
printf("p = %p\n", p);
}
a = 20
p = (nil)
The cipher used in this project:
Encrypts plain text messages consisting solely of the printable ASCII characters.
Decrypts ciphertext consisting solely of the printable ASCII characters.
The printable ASCII characters are 8-bit codes in the range of values from 32 to 126 (00100000 through 01111110). See ASCII Wikipedia
Any 8-bit sequences outside of this range constitutes invalid data.
Each cipher record must be of the form:
Action | lcg_m | , | lcg_c | , | Data | |
---|---|---|---|---|---|---|
1 char | 1-20 char | 1 char | 1-20 char | 1 char | any # of char | 1 char |
[Action:] Must be either ‘e’ or ‘d’ specifying encryption or decryption respectively.
[lcg_m:] Specifies a 64-bit positive integer used for m of a Linear Congruential Generator. Must be decimal digits.
[lcg_c:] Specifies a 64-bit positive integer used for c of a Linear Congruential Generator. Must be decimal digits.
[Data:] Printable ASCII character data to be encrypted or decrypted. Can be empty or arbitrarily long.
Determine the Linear Congruential Generator specified by the given key. This is done only once per line of input.
Read 1 byte of data b
Generate random value x
Compute encrypted byte as b XOR (x mod 128)
Deal with any non-printable ASCII characters.
Print the resulting character(s) to the standard output stream.
Return to step 2 and continue until the end of the line
Given a 128-bit symmetric key consisting of:
m : a 64-bit positive integer used as an LCG modulus,
c : a 64-bit positive integer used as an LCG increment.
Define a Linear Congruential Generator:
Xn + 1 = (aXn + c) mod m
$X_0 = c $
a = 1 + 2p, if 4 is a factor of m, otherwise, a = 1 + p.
p= product of m’s unique prime factors
Within each record, the data portion is the set of characters
between the second comma and '\n'
.
When encrypting:
Use getchar()
to read 1 byte of data to encrypt.
When decrypting: Reading in an encrypted byte may require reading 2 bytes from standard input since some character codes have 2-byte ciphertext representations.
Any character in the data segment not in the range of printable ASCII characters (32 to 126) is an error.
This cipher algorithm can generate target bytes that are outside the range of printable ASCII.
When encrypting, if a generated byte e
is:
Condition | Action |
---|---|
< 32 | Replace with two bytes: '\*' and '?'+e . |
= 127 | Replace with two bytes: '\*' and '$' . |
= '\*' |
Replace with two bytes: '\*' and '\*' . |
When decrypting, if a generated byte p
is a
non-printing ASCII character, then print the specified error message
and read to the end of line.
For every line of input, one line of output must be sent to the standard output stream.
If the input line is invalid, then the output has the form:
("%5d: %s Error\n", inputLineNumber, trash)
where trash
is any string no longer than twice the length of any data part of the line.
If the input line is valid, then the output has the form:
("%5d: %s\n", inputLineNumber, outStr)
Where outStr
is the encrypted or decrypted data.
Let’s walk through an example of encrypting step by step.
Input: e126,25,Byte\n
Given Key: m = 126 and c = 25
Calculate: a = 43
(2 × 3 × 7 + 1 since m = 126 = 2 × 3 × 3 × 7)
LCG: Xn + 1 = (43(Xn) + 25) mod 126 with X0 = 25
Data: Byte
B |
0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
y |
0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
t |
0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
e |
0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
You’ll be generating one value at a time in your program, I’m just demonstrating the sequence here.
In this example, we have Xi mod 128 = Xi since m = 126 < 128
This will not be the case with larger LCG values.
i | Xi | Xi mod 128 |
---|---|---|
0 | 25 | 25 |
1 | 92 | 92 |
2 | 75 | 75 |
3 | 100 | 100 |
4 | 41 | 41 |
5 | 24 | 24 |
6 | 49 | 49 |
7 | 116 | 116 |
… | … | … |
Data: | B |
66 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
Xi mod 128 | 25 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | |
encrypted | [ |
91 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
Data: | y |
121 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
Xi mod 128 | 92 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | |
encrypted | % |
37 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
Data: | t |
116 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
Xi mod 128 | 75 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | |
encrypted | ? |
63 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
Data: | e |
101 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
Xi mod 128 | 100 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | |
encrypted | *@ |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Byte
encrypts to [%?*@
Let’s walk through an example of decrypting step by step.
Input: d256,123,9*Z*P*P\n
Given Key: m = 256 and c = 123
Calculate: a = 5
(2 × 2 + 1 since m = 256 = 28)
LCG: Xn + 1 = (5(Xn) + 123) mod 126 with X0 = 123
Data: 9*Z*P*P
9 |
0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 |
*Z |
0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
*P |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
*P |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
ASCII | ||
'9' |
57 | |
'?' |
63 | |
'Z' |
90 | 'Z' - '?' is 27 |
'P' |
80 | 'P' - '?' is 17 |
You’ll be generating one value at a time in your program, I’m just demonstrating the sequence here.
This time around, the modulus operation actually matters, since 256 > 128
i | Xi | Xi mod 128 |
---|---|---|
0 | 123 | 123 |
1 | 226 | 98 |
2 | 229 | 101 |
3 | 244 | 116 |
… | … | … |
Data: | 9 |
57 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 |
Xi mod 128 | 123 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | |
decrypted | B |
66 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
Data: | *Z |
27 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
Xi mod 128 | 98 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | |
decrypted | y |
121 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
Data: | *P |
17 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
Xi mod 128 | 101 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | |
decrypted | t |
116 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
Data: | *P |
17 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
Xi mod 128 | 116 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | |
decrypted | e |
101 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
9*Z*P*P
decrypts to Byte
Let n be the number of which to find the prime factors.
Start with 2 as a test divisor.
If the test divisor squared is greater than the current n, then the current n is either 1 or prime. Save it if prime and return.
If the remainder of n divided by the test divisor is zero, then:
The test divisor is a prime factor of n. Save it.
Replace n with n divided by the test divisor.
Repeat b until test divisor is no longer a factor of n.
If, in step 4, the remainder of n divided by the test divisor was not zero, then increment the test divisor. Loop to step 3.
Write a function that finds the unique prime factors of a number, n, and stores each factor in an array. How big does the array need to be?
If n is a 64-bit integer then the largest number it can hold is 264 − 1.
Since 2 is the smallest prime, the largest 64-bit number must have less than 64 factors.
But only Unique Prime Factors are needed.
The product of the first 15 primes is:
2 × 3 × 5 × 7 × 11 × 13 × 17 × 19 × 23 × 29 × 31 × 37 × 41 × 43 × 47 = 11, 682, 905, 869, 181, 336, 790.
Times 53 > 264 − 1.