1 /** Practical One-time Pad Library
16 /** Show a list of all loaded pads. */
21 for (p
= pads
; p
; p
= p
->next
) {
22 printf("Pad: %s: %s\n", p
->name
, p
->local_filename
);
26 /** Open a companion offset file for given pad. Caller must close.
28 * @param mode Either "rt" or "wt", for reading or writing.
30 FILE *open_offset_file(PAD
*p
, char *mode
)
33 char *offset_filename
;
34 size_t filename_length
;
36 /* Offset is stored in a separate file; pad plus OFFSET_FILE_NAME_EXTENSION. */
37 filename_length
= strlen(p
->local_filename
) + strlen(OFFSET_FILE_EXTENSION
) + 1;
38 offset_filename
= malloc(filename_length
);
39 if (!offset_filename
) {
43 snprintf(offset_filename
, filename_length
, "%s" OFFSET_FILE_EXTENSION
, p
->local_filename
);
45 /* Read offset from file. */
46 ofp
= fopen(offset_filename
, mode
);
48 fprintf(stderr
, "opening offset file %s failed\n", offset_filename
);
50 free(offset_filename
);
53 free(offset_filename
);
58 /** Read the pad offset of a given pad. */
59 unsigned long read_offset(PAD
*p
)
62 char buffer
[OFFSET_SIZE
];
65 ofp
= open_offset_file(p
, "rt");
67 memset(buffer
, 0, OFFSET_SIZE
);
68 if (fread(buffer
, 1, OFFSET_SIZE
- 1, ofp
) < 1) {
69 fprintf(stderr
, "could not read offset file for %s\n", p
->local_filename
);
73 if (fclose(ofp
) != 0) {
74 fprintf(stderr
, "error closing offset file for reading for %s\n", p
->local_filename
);
79 /* We finally got it! */
80 offset
= strtoul(buffer
, NULL
, 10);
85 /** Write the pad offset to the given pad. */
86 void write_offset(PAD
*p
, unsigned long offset
)
89 char buffer
[OFFSET_SIZE
];
91 ofp
= open_offset_file(p
, "wt");
93 memset(buffer
, 0, OFFSET_SIZE
);
94 snprintf(buffer
, OFFSET_SIZE
- 1, "%ld", offset
);
95 printf("buffer=%s\n", buffer
);
96 if (fwrite(buffer
, strlen(buffer
), 1, ofp
) != 1) {
97 fprintf(stderr
, "write error saving offset %ld for %s\n", offset
, p
->local_filename
);
102 if (fclose(ofp
) != 0) {
103 fprintf(stderr
, "error closing offset file for writing for %s\n", p
->local_filename
);
109 /** Load a pad file from disk, adding to 'pads' global. */
110 void load_pad(char *local_filename
)
115 fp
= fopen("/Volumes/Not Backed Up/otp/otp-dazzlement", "rb");
121 new_pad
= malloc(sizeof(PAD
));
124 exit(EX_UNAVAILABLE
);
127 new_pad
->local_filename
= strdup(local_filename
);
128 new_pad
->name
= strdup("dc"); /* TODO */
130 new_pad
->next
= NULL
;
132 /* Add to linked list. */
139 for (p
= pads
; p
; p
= p
->next
)
141 tail
->next
= new_pad
;
145 /** Close all pads and free allocated memory. */
150 for (p
= pads
; p
; p
= next
) {
152 free(p
->local_filename
);
159 /** Unpackage a message packaged for transport. */
160 void unpackage(char *input
)
166 /** Format <v0.7 (pad name is unspecified; use default):
167 * MARKER_BEGIN + offset + comma
172 * MARKER_BEGIN + offset + comma + pad_name + comma
179 /* Locate where the message begins. */
180 s
= strstr(input
, MARKER_BEGIN
);
182 fprintf(stderr
, "unpackage: input |%s| lacks beginning marker %s\n",
183 input
, MARKER_BEGIN
);
188 end
= strstr(input
, MARKER_END
);
190 fprintf(stderr
, "unpackage: input |%s| lacks ending marker %s\n",
195 s
+= strlen(MARKER_BEGIN
);
196 msg
.offset
= strtoul(s
, &s
, 10);
198 printf("offset=%ld\n", msg
.offset
);
200 /* Move after mandatory comma. */
202 fprintf(stderr
, "unpackage: missing comma after offset, at |%s|, input |%s|\n",
208 memset(msg
.pad_name
, 0, PAD_NAME_LENGTH
);
210 /* Includes pad name? */
211 if (s
[0] != '\n' && s
[0] != '\r') {
215 /* v0.7+ message, includes pad name */
216 while(s
[0] != '\n' && s
[0] != '\r' && s
[0] != ',' && s
< end
) {
217 msg
.pad_name
[i
] = s
[0];
220 if (i
> PAD_NAME_LENGTH
) {
221 fprintf(stderr
, "unpackage: pad name length > maximum %d, in input |%s|\n",
222 PAD_NAME_LENGTH
, input
);
228 printf("Pad name: |%s|\n", msg
.pad_name
);
230 /* Go to next line */
231 while(s
[0] == '\n' || s
[0] == '\r' || s
[0] == ',' && (s
< end
))
236 /* Extract base64 data from end of message. */
237 msg
.cipher_text
= strdup(s
);
238 msg
.cipher_text
[end
- s
] = 0;
240 printf("b64_data=<%s>\n", msg
.cipher_text
);
242 /* TODO: free(msg.cipher_text); */