示例#1
0
def philox(W, N, ctr, key, Nrounds=None):
    """
    W: word length (32, 64)
    N: number of generated items, 2 or 4
    Nrounds: number of rounds (up to 16)
    inn: counter, array(N, numpy.uint${W}) --- counter
    k: key, array(N/2, numpy.uint${W}) --- key
    returns: array(N, numpy.uint${W})
    """
    assert W in (32, 64)
    assert N in (2, 4)

    if Nrounds is None:
        Nrounds = 10

    assert Nrounds <= 16

    with ignore_integer_overflow():
        for rnd in range(Nrounds):
            ctr = philox_round(W, N, rnd, ctr, key)

    return ctr
示例#2
0
def threefry(W, N, ctr, key, Nrounds=None):
    """
    W: word length (32, 64)
    N: number of generated items, 2 or 4
    Nrounds: number of rounds (up to 72)
    ctr: counter, array(N, numpy.uint${W})
    key: key, array(N, numpy.uint${W})
    returns: array(N, numpy.uint${W})

    Note: for W=64, N=4 and Nrounds=72 it is the same as Threefish algorithm from Skein,
    only without the 128-bit "tweak" which is applied to the key.
    With this tweak it is possible to upgrade this algorithm from PRNG to QRNG.
    """
    assert W in (32, 64)
    assert N in (2, 4)

    if Nrounds is None:
        Nrounds = 20

    dtype = numpy.uint32 if W == 32 else numpy.uint64

    if N == 2:
        assert Nrounds <= 32
        ks = numpy.empty(3, dtype)
    else:
        assert Nrounds <= 72
        ks = numpy.empty(5, dtype)

    X = numpy.empty(N, dtype)
    assert ctr.size == key.size == N

    ks[N] = THREEFRY_KS_PARITY[W]
    for i in range(N):
        ks[i] = key[i]
        X[i] = ctr[i]
        ks[N] ^= key[i]

    # Insert initial key before round 0
    for i in range(N):
        X[i] += ks[i]

    R = THREEFRY_ROTATION[(W, N)]

    with ignore_integer_overflow():
        for rnd in range(Nrounds):

            # FIXME: In the current version of Random123 (1.06),
            # there is a bug in R_idx calculation for N == 2, where
            #    R_idx = rnd % 8 if rnd < 20 else (rnd - 4) % 8
            # instead of what goes below.
            # When this bug is fixed, Random123 and this implementation
            # will start to produce identical results again,
            # and this comment can be removed.
            R_idx = rnd % 8

            if N == 2:
                X[0] += X[1]
                X[1] = threefry_rotate(W, R[R_idx, 0], X[1])
                X[1] ^= X[0]
            else:
                idx1 = 1 if rnd % 2 == 0 else 3
                idx2 = 3 if rnd % 2 == 0 else 1

                X[0] += X[idx1]
                X[idx1] = threefry_rotate(W, R[R_idx, 0], X[idx1])
                X[idx1] ^= X[0]

                X[2] += X[idx2]
                X[idx2] = threefry_rotate(W, R[R_idx, 1], X[idx2])
                X[idx2] ^= X[2]

            if rnd % 4 == 3:
                for i in range(N):
                    X[i] += ks[(rnd // 4 + i + 1) % (N + 1)]

                X[N-1] += dtype(rnd // 4 + 1)

    return X