blob: 973706f0a1bb10520a83c531b25a953f4534e7e6 (
plain) (
blame)
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
|
package org.gnunet.util.crypto;
import org.gnunet.construct.FixedSizeIntegerArray;
import org.gnunet.construct.Message;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class EddsaPrivateKey implements Message {
@FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
public byte[] d;
public EddsaSignature sign(EddsaPublicKey publicKey, int purpose, byte[] m) {
MessageDigest sha512;
try {
sha512 = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("crypto algorithm required but not provided");
}
byte[] h = sha512.digest(d);
BigInteger a = BigInteger.valueOf(2).pow(Ed25519.b-2);
for (int i = 3; i < (Ed25519.b - 2); i++) {
a = a.add(BigInteger.valueOf(2).pow(i).multiply(BigInteger.valueOf(bit(h,i))));
}
ByteBuffer rsub = ByteBuffer.allocate((Ed25519.b/8)+m.length);
rsub.put(h, Ed25519.b/8, Ed25519.b/4-Ed25519.b/8).put(m);
BigInteger r = Ed25519.Hint(rsub.array());
Ed25519 R = Ed25519.B.scalarmult(r);
byte[] encodedPublicKey = publicKey.asPoint().encode();
ByteBuffer buf = ByteBuffer.allocate(32 + encodedPublicKey.length + m.length);
buf.put(R.encode()).put(encodedPublicKey).put(m);
BigInteger S = r.add(Ed25519.Hint(buf.array()).multiply(a)).mod(Ed25519.l);
return new EddsaSignature(R, S);
}
/**
* Get return the i-th bit in the given array of bytes h.
*
* @param h array of bytes
* @param i bit index
* @return i-th bit in h
*/
private static int bit(byte[] h, int i) {
return h[i/8] >> (i%8) & 1;
}
private BigInteger computePublicKeyCoefficient() {
MessageDigest sha512;
try {
sha512 = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("crypto algorithm required but not provided");
}
byte[] h = sha512.digest(d);
BigInteger a = BigInteger.valueOf(2).pow(Ed25519.b - 2);
for (int i=3; i < (Ed25519.b - 2); i++) {
BigInteger apart = BigInteger.valueOf(2).pow(i).multiply(BigInteger.valueOf(bit(h,i)));
a = a.add(apart);
}
return a;
}
public EddsaPublicKey getPublicKey() {
BigInteger a = computePublicKeyCoefficient();
Ed25519 A = Ed25519.B.scalarmult(a);
return new EddsaPublicKey(A);
}
public static EddsaPrivateKey createRandom() {
SecureRandom sr = new SecureRandom();
EddsaPrivateKey privateKey = new EddsaPrivateKey();
privateKey.d = new byte[32];
sr.nextBytes(privateKey.d);
return privateKey;
}
}
|