
com.subgraph.orchid.crypto.Curve25519 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of actor-api-tor Show documentation
Show all versions of actor-api-tor Show documentation
Actor Tor plugin for Actor API
The newest version!
package com.subgraph.orchid.crypto;
//
// Copyright (c) 2011, Neil Alexander T.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with
// or without modification, are permitted provided that the following
// conditions are met:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
/*
* https://github.com/neilalexander/jnacl/blob/master/crypto/curve25519.java
*/
public class Curve25519
{
final int CRYPTO_BYTES = 32;
final int CRYPTO_SCALARBYTES = 32;
static byte[] basev = { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static int[] minusp = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 };
public static int crypto_scalarmult_base(byte[] q, byte[] n)
{
byte[] basevp = basev;
return crypto_scalarmult(q, n, basevp);
}
static void add(int[] outv, int outvoffset, int[] a, int aoffset, int[] b, int boffset)
{
int u = 0;
for (int j = 0; j < 31; ++j)
{
u += a[aoffset + j] + b[boffset + j];
outv[outvoffset + j] = u & 255;
u >>>= 8;
}
u += a[aoffset + 31] + b[boffset + 31];
outv[outvoffset + 31] = u;
}
static void sub(int[] outv, int outvoffset, int[] a, int aoffset, int[] b, int boffset)
{
int u = 218;
for (int j = 0; j < 31; ++j)
{
u += a[aoffset + j] + 65280 - b[boffset + j];
outv[outvoffset + j] = u & 255;
u >>>= 8;
}
u += a[aoffset + 31] - b[boffset + 31];
outv[outvoffset + 31] = u;
}
static void squeeze(int[] a, int aoffset)
{
int u = 0;
for (int j = 0; j < 31; ++j)
{
u += a[aoffset + j];
a[aoffset + j] = u & 255;
u >>>= 8;
}
u += a[aoffset + 31];
a[aoffset + 31] = u & 127;
u = 19 * (u >>> 7);
for (int j = 0; j < 31; ++j)
{
u += a[aoffset + j];
a[aoffset + j] = u & 255;
u >>>= 8;
}
u += a[aoffset + 31];
a[aoffset + 31] = u;
}
static void freeze(int[] a, int aoffset)
{
int[] aorig = new int[32];
for (int j = 0; j < 32; ++j)
aorig[j] = a[aoffset + j];
int[] minuspp = minusp;
add(a, 0, a, 0, minuspp, 0);
int negative = (int) (-((a[aoffset + 31] >>> 7) & 1));
for (int j = 0; j < 32; ++j)
a[aoffset + j] ^= negative & (aorig[j] ^ a[aoffset + j]);
}
static void mult(int[] outv, int outvoffset, int[] a, int aoffset, int[] b, int boffset)
{
int j;
for (int i = 0; i < 32; ++i)
{
int u = 0;
for (j = 0; j <= i; ++j)
u += a[aoffset + j] * b[boffset + i - j];
for (j = i + 1; j < 32; ++j)
u += 38 * a[aoffset + j] * b[boffset + i + 32 - j];
outv[outvoffset + i] = u;
}
squeeze(outv, outvoffset);
}
static void mult121665(int[] outv, int[] a)
{
int j;
int u = 0;
for (j = 0; j < 31; ++j)
{
u += 121665 * a[j];
outv[j] = u & 255;
u >>>= 8;
}
u += 121665 * a[31];
outv[31] = u & 127;
u = 19 * (u >>> 7);
for (j = 0; j < 31; ++j)
{
u += outv[j];
outv[j] = u & 255;
u >>>= 8;
}
u += outv[j];
outv[j] = u;
}
static void square(int[] outv, int outvoffset, int[] a, int aoffset)
{
int j;
for (int i = 0; i < 32; ++i)
{
int u = 0;
for (j = 0; j < i - j; ++j)
u += a[aoffset + j] * a[aoffset + i - j];
for (j = i + 1; j < i + 32 - j; ++j)
u += 38 * a[aoffset + j] * a[aoffset + i + 32 - j];
u *= 2;
if ((i & 1) == 0)
{
u += a[aoffset + i / 2] * a[aoffset + i / 2];
u += 38 * a[aoffset + i / 2 + 16] * a[aoffset + i / 2 + 16];
}
outv[outvoffset + i] = u;
}
squeeze(outv, outvoffset);
}
static void select(int[] p, int[] q, int[] r, int[] s, int b)
{
int bminus1 = b - 1;
for (int j = 0; j < 64; ++j)
{
int t = bminus1 & (r[j] ^ s[j]);
p[j] = s[j] ^ t;
q[j] = r[j] ^ t;
}
}
static void mainloop(int[] work, byte[] e)
{
int[] xzm1 = new int[64];
int[] xzm = new int[64];
int[] xzmb = new int[64];
int[] xzm1b = new int[64];
int[] xznb = new int[64];
int[] xzn1b = new int[64];
int[] a0 = new int[64];
int[] a1 = new int[64];
int[] b0 = new int[64];
int[] b1 = new int[64];
int[] c1 = new int[64];
int[] r = new int[32];
int[] s = new int[32];
int[] t = new int[32];
int[] u = new int[32];
for (int j = 0; j < 32; ++j)
xzm1[j] = work[j];
xzm1[32] = 1;
for (int j = 33; j < 64; ++j)
xzm1[j] = 0;
xzm[0] = 1;
for (int j = 1; j < 64; ++j)
xzm[j] = 0;
int[] xzmbp = xzmb, a0p = a0, xzm1bp = xzm1b;
int[] a1p = a1, b0p = b0, b1p = b1, c1p = c1;
int[] xznbp = xznb, up = u, xzn1bp = xzn1b;
int[] workp = work, sp = s, rp = r;
for (int pos = 254; pos >= 0; --pos)
{
int b = ((int) ((e[pos / 8] & 0xFF) >>> (pos & 7)));
b &= 1;
select(xzmb, xzm1b, xzm, xzm1, b);
add(a0, 0, xzmb, 0, xzmbp, 32);
sub(a0p, 32, xzmb, 0, xzmbp, 32);
add(a1, 0, xzm1b, 0, xzm1bp, 32);
sub(a1p, 32, xzm1b, 0, xzm1bp, 32);
square(b0p, 0, a0p, 0);
square(b0p, 32, a0p, 32);
mult(b1p, 0, a1p, 0, a0p, 32);
mult(b1p, 32, a1p, 32, a0p, 0);
add(c1, 0, b1, 0, b1p, 32);
sub(c1p, 32, b1, 0, b1p, 32);
square(rp, 0, c1p, 32);
sub(sp, 0, b0, 0, b0p, 32);
mult121665(t, s);
add(u, 0, t, 0, b0p, 0);
mult(xznbp, 0, b0p, 0, b0p, 32);
mult(xznbp, 32, sp, 0, up, 0);
square(xzn1bp, 0, c1p, 0);
mult(xzn1bp, 32, rp, 0, workp, 0);
select(xzm, xzm1, xznb, xzn1b, b);
}
for (int j = 0; j < 64; ++j)
work[j] = xzm[j];
}
static void recip(int[] outv, int outvoffset, int[] z, int zoffset)
{
int[] z2 = new int[32];
int[] z9 = new int[32];
int[] z11 = new int[32];
int[] z2_5_0 = new int[32];
int[] z2_10_0 = new int[32];
int[] z2_20_0 = new int[32];
int[] z2_50_0 = new int[32];
int[] z2_100_0 = new int[32];
int[] t0 = new int[32];
int[] t1 = new int[32];
/* 2 */
int[] z2p = z2;
square(z2p, 0, z, zoffset);
/* 4 */
square(t1, 0, z2, 0);
/* 8 */
square(t0, 0, t1, 0);
/* 9 */
int[] z9p = z9, t0p = t0;
mult(z9p, 0, t0p, 0, z, zoffset);
/* 11 */
mult(z11, 0, z9, 0, z2, 0);
/* 22 */
square(t0, 0, z11, 0);
/* 2^5 - 2^0 = 31 */
mult(z2_5_0, 0, t0, 0, z9, 0);
/* 2^6 - 2^1 */
square(t0, 0, z2_5_0, 0);
/* 2^7 - 2^2 */
square(t1, 0, t0, 0);
/* 2^8 - 2^3 */
square(t0, 0, t1, 0);
/* 2^9 - 2^4 */
square(t1, 0, t0, 0);
/* 2^10 - 2^5 */
square(t0, 0, t1, 0);
/* 2^10 - 2^0 */
mult(z2_10_0, 0, t0, 0, z2_5_0, 0);
/* 2^11 - 2^1 */
square(t0, 0, z2_10_0, 0);
/* 2^12 - 2^2 */
square(t1, 0, t0, 0);
/* 2^20 - 2^10 */
for (int i = 2; i < 10; i += 2)
{
square(t0, 0, t1, 0);
square(t1, 0, t0, 0);
}
/* 2^20 - 2^0 */
mult(z2_20_0, 0, t1, 0, z2_10_0, 0);
/* 2^21 - 2^1 */
square(t0, 0, z2_20_0, 0);
/* 2^22 - 2^2 */
square(t1, 0, t0, 0);
/* 2^40 - 2^20 */
for (int i = 2; i < 20; i += 2)
{
square(t0, 0, t1, 0);
square(t1, 0, t0, 0);
}
/* 2^40 - 2^0 */
mult(t0, 0, t1, 0, z2_20_0, 0);
/* 2^41 - 2^1 */
square(t1, 0, t0, 0);
/* 2^42 - 2^2 */
square(t0, 0, t1, 0);
/* 2^50 - 2^10 */
for (int i = 2; i < 10; i += 2)
{
square(t1, 0, t0, 0);
square(t0, 0, t1, 0);
}
/* 2^50 - 2^0 */
mult(z2_50_0, 0, t0, 0, z2_10_0, 0);
/* 2^51 - 2^1 */
square(t0, 0, z2_50_0, 0);
/* 2^52 - 2^2 */
square(t1, 0, t0, 0);
/* 2^100 - 2^50 */
for (int i = 2; i < 50; i += 2)
{
square(t0, 0, t1, 0);
square(t1, 0, t0, 0);
}
/* 2^100 - 2^0 */
mult(z2_100_0, 0, t1, 0, z2_50_0, 0);
/* 2^101 - 2^1 */
square(t1, 0, z2_100_0, 0);
/* 2^102 - 2^2 */
square(t0, 0, t1, 0);
/* 2^200 - 2^100 */
for (int i = 2; i < 100; i += 2)
{
square(t1, 0, t0, 0);
square(t0, 0, t1, 0);
}
/* 2^200 - 2^0 */
mult(t1, 0, t0, 0, z2_100_0, 0);
/* 2^201 - 2^1 */
square(t0, 0, t1, 0);
/* 2^202 - 2^2 */
square(t1, 0, t0, 0);
/* 2^250 - 2^50 */
for (int i = 2; i < 50; i += 2)
{
square(t0, 0, t1, 0);
square(t1, 0, t0, 0);
}
/* 2^250 - 2^0 */
mult(t0, 0, t1, 0, z2_50_0, 0);
/* 2^251 - 2^1 */
square(t1, 0, t0, 0);
/* 2^252 - 2^2 */
square(t0, 0, t1, 0);
/* 2^253 - 2^3 */
square(t1, 0, t0, 0);
/* 2^254 - 2^4 */
square(t0, 0, t1, 0);
/* 2^255 - 2^5 */
square(t1, 0, t0, 0);
/* 2^255 - 21 */
int[] t1p = t1, z11p = z11;
mult(outv, outvoffset, t1p, 0, z11p, 0);
}
public static int crypto_scalarmult(byte[] q, byte[] n, byte[] p)
{
int[] work = new int[96];
byte[] e = new byte[32];
for (int i = 0; i < 32; ++i)
e[i] = n[i];
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
for (int i = 0; i < 32; ++i)
work[i] = p[i] & 0xFF;
mainloop(work, e);
recip(work, 32, work, 32);
mult(work, 64, work, 0, work, 32);
freeze(work, 64);
for (int i = 0; i < 32; ++i)
q[i] = (byte) work[64 + i];
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy