1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "standard.h"
#include "rand.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct session_token_ctx {
int mask;
int count;
int curr_word;
int bytes_left_in_curr_word;
struct randctx isaac_ctx;
char *alphabet;
size_t alphabet_length;
size_t token_length;
};
typedef struct session_token_ctx * Session_Token;
static inline int get_new_byte(struct session_token_ctx *ctx) {
int output;
if (ctx->bytes_left_in_curr_word == 0) {
if (ctx->count > 255) {
isaac(&ctx->isaac_ctx);
ctx->count = 0;
}
ctx->curr_word = ctx->isaac_ctx.randrsl[ctx->count];
ctx->count++;
ctx->bytes_left_in_curr_word = 4;
}
output = ctx->curr_word & 0xFF;
ctx->bytes_left_in_curr_word--;
ctx->curr_word >>= 8;
return output;
}
static int get_mask(int v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
return v;
}
MODULE = Session::Token PACKAGE = Session::Token
PROTOTYPES: ENABLE
Session_Token
_new_context(seed, alphabet, token_length)
SV *seed
SV *alphabet
size_t token_length
CODE:
struct session_token_ctx *ctx;
char *seedp;
size_t len;
len = SvCUR(seed);
seedp = SvPV(seed, len);
assert(sizeof(ctx->isaac_ctx.randrsl) == 1024);
if (len != 1024) {
croak("unexpected seed length: %lu", len);
}
ctx = malloc(sizeof(struct session_token_ctx));
memset(ctx, '\0', sizeof(struct session_token_ctx));
memcpy(&ctx->isaac_ctx.randrsl, seedp, 1024);
randinit(&ctx->isaac_ctx, TRUE);
isaac(&ctx->isaac_ctx);
ctx->alphabet_length = SvCUR(alphabet);
ctx->alphabet = malloc(ctx->alphabet_length);
memcpy(ctx->alphabet, SvPV(alphabet, ctx->alphabet_length), ctx->alphabet_length);
ctx->token_length = token_length;
ctx->mask = get_mask(ctx->alphabet_length);
RETVAL = ctx;
OUTPUT:
RETVAL
void
DESTROY(ctx)
Session_Token ctx
CODE:
free(ctx->alphabet);
free(ctx);
SV *
get(ctx)
Session_Token ctx
CODE:
SV *output;
char *outputp;
size_t i, curr;
output = newSVpvn("", 0);
SvGROW(output, ctx->token_length);
SvCUR_set(output, ctx->token_length);
outputp = SvPV(output, ctx->token_length);
for (i=0; i<ctx->token_length; i++) {
while((curr = (get_new_byte(ctx) & ctx->mask)) >= ctx->alphabet_length) ;
outputp[i] = ctx->alphabet[curr];
}
RETVAL = output;
OUTPUT:
RETVAL
|