File: Ed25519Provider.java

package info (click to toggle)
ruby-ed25519 1.4.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 668 kB
  • sloc: ansic: 3,789; java: 3,112; ruby: 103; makefile: 6
file content (95 lines) | stat: -rw-r--r-- 4,148 bytes parent folder | download | duplicates (4)
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
package org.cryptorb;

import java.security.MessageDigest;
import java.security.Signature;
import java.util.Arrays;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

@JRubyModule(name="Ed25519::Provider::JRuby")
public class Ed25519Provider {
	public static RubyModule createEd25519Module(Ruby runtime) {
		RubyModule mEd25519 = runtime.defineModule("Ed25519");
		RubyModule mEd25519Provider = mEd25519.defineModuleUnder("Provider");
		RubyModule mEd25519ProviderJRuby = mEd25519Provider.defineOrGetModuleUnder("JRuby");
		mEd25519ProviderJRuby.defineAnnotatedMethods(Ed25519Provider.class);

		return mEd25519ProviderJRuby;
	}

	@JRubyMethod(name = "create_keypair", module = true)
	public static IRubyObject create_keypair(ThreadContext context, IRubyObject self, IRubyObject seed) {
		byte[] seedBytes = seed.convertToString().getByteList().bytes();

		if (seedBytes.length != 32) {
			throw context.runtime.newArgumentError("expected 32-byte seed value, got " + seedBytes.length);
		}

		EdDSAParameterSpec edParams = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
                EdDSAPrivateKeySpec signingKey = new EdDSAPrivateKeySpec(seedBytes, edParams);
                EdDSAPublicKeySpec verifyKey = new EdDSAPublicKeySpec(signingKey.getA(), edParams);

		byte[] keypair = new byte[64];

		System.arraycopy(seedBytes, 0, keypair, 0, 32);
		System.arraycopy(verifyKey.getA().toByteArray(), 0, keypair, 32, 32);

		return RubyString.newString(context.getRuntime(), keypair);
	}

	@JRubyMethod(name = "sign", module = true)
	public static IRubyObject sign(ThreadContext context, IRubyObject self, IRubyObject keypair, IRubyObject msg) throws Exception {
		byte[] keypairBytes = keypair.convertToString().getByteList().bytes();

		if (keypairBytes.length != 64) {
			throw context.runtime.newArgumentError("expected 64-byte keypair value, got " + keypairBytes.length);
		}

                EdDSAParameterSpec edParams = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
                Signature signer = new EdDSAEngine(MessageDigest.getInstance(edParams.getHashAlgorithm()));

		byte[] seedBytes = Arrays.copyOfRange(keypairBytes, 0, 32);
		EdDSAPrivateKeySpec signingKey = new EdDSAPrivateKeySpec(seedBytes, edParams);

                signer.initSign(new EdDSAPrivateKey(signingKey));
                signer.update(msg.convertToString().getByteList().bytes());

		return RubyString.newString(context.getRuntime(), signer.sign());
	}

	@JRubyMethod(name = "verify", module = true)
	public static IRubyObject verify(ThreadContext context, IRubyObject self, IRubyObject verify_key, IRubyObject signature, IRubyObject msg) throws Exception {
		byte[] verifyKeyBytes = verify_key.convertToString().getByteList().bytes();
		byte[] signatureBytes = signature.convertToString().getByteList().bytes();

		if (verifyKeyBytes.length != 32) {
			throw context.runtime.newArgumentError("expected 32-byte verify key, got " + verifyKeyBytes.length);
		}

		if (signatureBytes.length != 64) {
			throw context.runtime.newArgumentError("expected 64-byte signature, got " + signatureBytes.length);
		}

		EdDSAParameterSpec edParams = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
		Signature signer = new EdDSAEngine(MessageDigest.getInstance(edParams.getHashAlgorithm()));
		EdDSAPublicKeySpec verifyKey = new EdDSAPublicKeySpec(verifyKeyBytes, edParams);

		signer.initVerify(new EdDSAPublicKey(verifyKey));
		signer.update(msg.convertToString().getByteList().bytes());

		boolean isValid = signer.verify(signatureBytes);
		return context.runtime.newBoolean(isValid);
	}
}