Skip to content

Commit fb70043

Browse files
committed
added javadoc to private key
1 parent e16fbe4 commit fb70043

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

src/de/ntcomputer/crypto/eddsa/Ed25519PrivateKey.java

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
4141
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
4242

43+
/**
44+
* A wrapper class which makes it easy to generate and use Ed25519 private keys.
45+
* All methods are using java's {@link SecureRandom} PRNG, if a PRNG is needed.
46+
* All sign methods are using the {@link HashCondenser} for efficiency.
47+
*
48+
* @author DevCybran
49+
*
50+
*/
4351
public class Ed25519PrivateKey implements Destroyable {
4452
static final EdDSAParameterSpec P_SPEC = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
4553
private static SecureRandom random = null;
@@ -70,11 +78,34 @@ static byte[] hash(byte[] data) throws NoSuchAlgorithmException {
7078
return md.digest(data);
7179
}
7280

81+
/**
82+
* Loads a private key from the specified file.
83+
*
84+
* @param privateKeyFile the file to read the private key from
85+
* @param password the password which was passed to {@link #saveAsFile(File, char[])} upon saving the file
86+
* @return the read private key
87+
* @throws IOException if an IO error occurs while reading the file
88+
* @throws IllegalArgumentException if password is null
89+
* @throws NoSuchAlgorithmException if either of the encryption algorithms is not present on this machine
90+
* @throws NoSuchPaddingException if the PKCS5 padding is not present on this machine
91+
* @throws InvalidKeyException if the passed privatKeyString has an invalid format
92+
*/
7393
public static Ed25519PrivateKey loadFromFile(File privateKeyFile, char[] password) throws IllegalArgumentException, IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
7494
String key = new String(Files.readAllBytes(privateKeyFile.toPath()), StandardCharsets.UTF_8);
7595
return loadFromString(key, password);
7696
}
7797

98+
/**
99+
* Decodes a private key from the specified string.
100+
*
101+
* @param privateKeyString A hexadecimal encoded representation of the key, generated by {@link #saveAsString(char[])}
102+
* @param password the password which was passed to {@link #saveAsString(char[])} upon generating the privateKeyString
103+
* @return the decoded private key
104+
* @throws IllegalArgumentException if password is null
105+
* @throws NoSuchAlgorithmException if either of the encryption algorithms is not present on this machine
106+
* @throws NoSuchPaddingException if the PKCS5 padding is not present on this machine
107+
* @throws InvalidKeyException if the passed privatKeyString has an invalid format
108+
*/
78109
public static Ed25519PrivateKey loadFromString(String privateKeyString, char[] password) throws IllegalArgumentException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
79110
if(privateKeyString.length() < (512+128+256+512)/8*2) throw new InvalidKeyException("the supplied key is not a valid private key"); // salt + iv + key + hash
80111
byte[] salt, iv, encryptedKey;
@@ -110,6 +141,13 @@ public static Ed25519PrivateKey loadFromString(String privateKeyString, char[] p
110141
}
111142
}
112143

144+
/**
145+
* Generates a new private key.
146+
* {@link SecureRandom} is used as a source to seed this key.
147+
*
148+
*
149+
* @return A new private key
150+
*/
113151
public static Ed25519PrivateKey generate() {
114152
KeyPairGenerator gen = new KeyPairGenerator();
115153
try {
@@ -126,11 +164,33 @@ private Ed25519PrivateKey(EdDSAPrivateKey key, Ed25519PublicKey pubKey) {
126164
this.pubKey = pubKey;
127165
}
128166

167+
/**
168+
* Encrypts, encodes and saves this key to the specified file.
169+
*
170+
* @see #saveAsString(char[])
171+
* @param privateKeyFile the file to save the private key to
172+
* @param password a password for encrypting the private key. The longer, the better.
173+
* @throws IllegalArgumentException if password is null
174+
* @throws IOException if an IO error occurs when writing the file
175+
* @throws NoSuchAlgorithmException if either of the encryption algorithms is not present on this machine
176+
* @throws NoSuchPaddingException if the PKCS5 padding is not present on this machine
177+
*/
129178
public void saveAsFile(File privateKeyFile, char[] password) throws IllegalArgumentException, IOException, NoSuchAlgorithmException, NoSuchPaddingException {
130179
String key = this.saveAsString(password);
131180
Files.write(privateKeyFile.toPath(), key.getBytes(StandardCharsets.UTF_8));
132181
}
133182

183+
/**
184+
* Encodes this key as a hexadecimal String.
185+
* A password is used to encrypt this key. The password and a generated 512-bit long salt are fed to 1 million iterations of PBKDF2 with SHA-512 to generate a secret key.
186+
* The secret key is used to encrypt the private key using AES-256-CBC-PKCS5.
187+
*
188+
* @param password a password for encrypting the private key. The longer, the better.
189+
* @return a hexadecimal encoded and encrypted representation of this private key
190+
* @throws IllegalArgumentException if password is null
191+
* @throws NoSuchAlgorithmException if either of the encryption algorithms is not present on this machine
192+
* @throws NoSuchPaddingException if the PKCS5 padding is not present on this machine
193+
*/
134194
public String saveAsString(char[] password) throws IllegalArgumentException, NoSuchAlgorithmException, NoSuchPaddingException {
135195
byte[] salt = new byte[512/8];
136196
random().nextBytes(salt);
@@ -158,6 +218,11 @@ public String saveAsString(char[] password) throws IllegalArgumentException, NoS
158218
}
159219
}
160220

221+
/**
222+
* Creates (if necessary) and returns the public key for this private key.
223+
*
224+
* @return the public key for this private key
225+
*/
161226
public Ed25519PublicKey derivePublicKey() {
162227
if(this.pubKey==null) {
163228
this.pubKey = new Ed25519PublicKey(new EdDSAPublicKey(new EdDSAPublicKeySpec(this.key.getA(), this.key.getParams())));
@@ -178,18 +243,55 @@ private String signLow(byte[] data) {
178243
}
179244
}
180245

246+
/**
247+
* Signs the given byte array.
248+
* {@link HashCondenser#compute(byte[])} with default settings is preprocessing the array before signing it.
249+
*
250+
* @param data
251+
* @return a hexadecimal representation of the signature
252+
* @throws NoSuchAlgorithmException if the hash algorithm is not present on this machine
253+
*/
181254
public String sign(byte[] data) throws NoSuchAlgorithmException {
182255
return signLow(HashCondenser.getInstance().compute(data));
183256
}
184257

258+
/**
259+
* Signs the given String by converting it to bytes using the UTF-8 charset.
260+
*
261+
* @see #sign(byte[])
262+
* @param data
263+
* @return a hexadecimal representation of the signature
264+
* @throws NoSuchAlgorithmException if the hash algorithm is not present on this machine
265+
*/
185266
public String sign(String data) throws NoSuchAlgorithmException {
186267
return this.sign(data.getBytes(StandardCharsets.UTF_8));
187268
}
188269

270+
/**
271+
* Signs all data which can be read from the given InputStream.
272+
* {@link HashCondenser#compute(byte[])} with default settings is preprocessing the stream before signing it, which will allow signing huge files.
273+
*
274+
* @param source the data source
275+
* @param sourceSize the exact size of all data which will pass through the InputStream
276+
* @return a hexadecimal representation of the signature
277+
* @throws IllegalArgumentException if sourceSize is not the correct size
278+
* @throws NoSuchAlgorithmException if the hash algorithm is not present on this machine
279+
* @throws IOException if an IO error occurs while reading the stream
280+
*/
189281
public String sign(InputStream source, long sourceSize) throws IllegalArgumentException, NoSuchAlgorithmException, IOException {
190282
return signLow(HashCondenser.getInstance().compute(source, sourceSize));
191283
}
192284

285+
/**
286+
* Signs the content of the given file.
287+
*
288+
* @see #sign(InputStream, long)
289+
* @param source
290+
* @return a hexadecimal representation of the signature
291+
* @throws IOException if an IO error occurs while reading the file
292+
* @throws IllegalArgumentException if the file's size changes during computation
293+
* @throws NoSuchAlgorithmException if the hash algorithm is not present on this machine
294+
*/
193295
public String sign(File source) throws IOException, IllegalArgumentException, NoSuchAlgorithmException {
194296
if(!source.isFile()) throw new FileNotFoundException(source.getAbsolutePath());
195297
long fileSize = source.length();
@@ -198,10 +300,30 @@ public String sign(File source) throws IOException, IllegalArgumentException, No
198300
}
199301
}
200302

303+
/**
304+
* Signs the content of the given file and writes the signature to a file of the same name which has a ".sig" extension appended
305+
* Example: If you sign "MyFile.dat", the signature will be written to "MyFile.dat.sig"
306+
*
307+
* @see #signToFile(File, File)
308+
* @param source
309+
* @throws IOException if an IO error occurs while reading the file
310+
* @throws IllegalArgumentException if the file's size changes during computation
311+
* @throws NoSuchAlgorithmException if the hash algorithm is not present on this machine
312+
*/
201313
public void signToFile(File source) throws IOException, IllegalArgumentException, NoSuchAlgorithmException {
202314
this.signToFile(source, new File(source, ".sig"));
203315
}
204316

317+
/**
318+
* Signs the content of the given source file and writes the signature to the given signature file.
319+
*
320+
* @see #sign(File)
321+
* @param source
322+
* @param signatureFile the file to write the signature to
323+
* @throws IOException if an IO error occurs while reading the file
324+
* @throws IllegalArgumentException if the file's size changes during computation
325+
* @throws NoSuchAlgorithmException if the hash algorithm is not present on this machine
326+
*/
205327
public void signToFile(File source, File signatureFile) throws IOException, IllegalArgumentException, NoSuchAlgorithmException {
206328
String signature = this.sign(source);
207329
Files.write(signatureFile.toPath(), signature.getBytes(StandardCharsets.UTF_8));

0 commit comments

Comments
 (0)