jami-dht: Updated SunEC elliptical curve provider for BouncyCastle

Change-Id: I6ebebac1fa381686377efb6fe636c0cf36e66a80
This commit is contained in:
Philippe Larose
2024-02-22 16:29:32 -05:00
parent 1f4bee3d95
commit 07f7adea06
6 changed files with 139 additions and 34 deletions

20
.vscode/launch.json vendored
View File

@ -6,10 +6,26 @@
"configurations": [
{
"type": "java",
"name": "Attach Debugger",
"name": "Debug JamsProd",
"request": "attach",
"hostName": "192.168.50.255",
"port": 8000,
"projectName": "jams-server"
},
{
"type": "java",
"name": "Debug JamsLocal",
"request": "attach",
"hostName": "192.168.51.70",
"port": 5002,
"projectName": "jams-server"
},
{
"type": "java",
"name": "Debug JamsDev",
"request": "attach",
"hostName": "localhost",
"port": 35000,
"port": 5002,
"projectName": "jams-server"
}
]

View File

@ -177,15 +177,17 @@ TYPE=$(xdg-mime query filetype datastore/target/site/jacoco/index.html)
xdg-mime default firefox.desktop "$TYPE"
```
## Visualize the derby database
The IntelliJ Ultimate Edition Database view can help visualize the database schema.
Don't forget to launch jams locally at least once before proceeding.
1. Open this project in IntelliJ
2. View -> Tool Windows -> Database
3. Plus icon -> Data Source from Path
4. Select the jami-jams/jams/jams folder
5. Select the Apache Derby (Embedded) driver
6. Select No auth, click Ok, refresh the database window and the tables should appear!
## Access the derby database
The DBeaver Community software can help visualize the database schema. You can install it from its [official website](https://dbeaver.io/download/). Once installed, here are the steps to access the database:
1. On the top left, select New Database Connection (Shift+Ctrl+N).
2. Select Derby Embedded from the list.
3. Choose Connect by: host.
4. Select the jami-jams/jams/jams folder in Path
5. Leave Username and Password empty and click finish
6. The database data can new be viewed under jams->APP->TABLES
You can also use Apache Derby's official [ij cli tool](https://db.apache.org/derby/papers/DerbyTut/ij_intro.html) to access the database.
## About jams-server/src/main/java/net/jami/jams/server/filters
The files in the `filters` folder are prefixed "A", "B", "C" and "D" so that the

View File

@ -44,8 +44,11 @@ public class RegisterUserFlow {
user.getX509Fields().setCommonName(user.getUsername());
user = certificateAuthority.getSignedCertificate(user);
String[] ethKeyPair = null;
while (ethKeyPair == null) {
try {
ethKeyPair = ETHAddressGenerator.generateAddress();
} catch (Exception e) {
log.error("Error generating ETH address", e);
return false;
}
user.setEthAddress(ethKeyPair[0]);
user.setEthKey(ethKeyPair[1]);

View File

@ -0,0 +1,63 @@
package net.jami.jams.authmodule;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import net.jami.datastore.main.DataStore;
import net.jami.jams.common.cryptoengineapi.CertificateAuthority;
import net.jami.jams.common.jami.NameServer;
import net.jami.jams.common.objects.user.AccessLevel;
import net.jami.jams.common.objects.user.User;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.io.File;
@ExtendWith(MockitoExtension.class)
class RegisterUserFlowTest {
@Mock private static DataStore dataStoreMock;
@Mock private static CertificateAuthority certificateAuthorityMock;
@Mock private NameServer nameServer;
private static UserAuthenticationModule userAuthModule;
@BeforeEach
void setUp() {
mockStatic(UserAuthenticationModule.class);
try {
userAuthModule = new UserAuthenticationModule(dataStoreMock, certificateAuthorityMock);
} catch (Exception e) {
e.printStackTrace();
}
}
@AfterAll
public static void tearDown() {
// Remove generated key files
File pubkeyFile = new File(System.getProperty("user.dir") + File.separator + "oauth.pub");
if (pubkeyFile.exists()) {
pubkeyFile.delete();
}
File privateKeyFile =
new File(System.getProperty("user.dir") + File.separator + "oauth.key");
if (privateKeyFile.exists()) {
privateKeyFile.delete();
}
}
@Test
void createUser() throws Exception {
User user = new User();
when(certificateAuthorityMock.getSignedCertificate(any(User.class))).thenReturn(user);
user.setUsername("Test User");
user.setAccessLevel(AccessLevel.USER);
RegisterUserFlow.createUser(user, nameServer);
Assertions.assertNotNull(user.getAddress(), "User ETHAddress was not generated!");
}
}

View File

@ -44,38 +44,39 @@ import net.jami.jams.dht.hashutils.HexBin;
import net.jami.jams.dht.hashutils.Keccak256;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
public class ETHAddressGenerator {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static String[] generateAddress() {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "SunEC");
keyGen.initialize(new ECGenParameterSpec("secp256k1"));
// Generate the Public and Private Keys
KeyPair pair = keyGen.generateKeyPair();
ECPrivateKey ecpriv = (ECPrivateKey) pair.getPrivate();
ECPublicKey ecpub = (ECPublicKey) pair.getPublic();
public static String[] generateAddress() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "BC");
keyGen.initialize(new ECGenParameterSpec("secp256k1"));
// Generate the Public and Private Keys
KeyPair pair = keyGen.generateKeyPair();
ECPrivateKey ecpriv = (ECPrivateKey) pair.getPrivate();
ECPublicKey ecpub = (ECPublicKey) pair.getPublic();
// Get the hex representations we need.
String hexPubKey =
ecpub.getW().getAffineX().toString(16) + ecpub.getW().getAffineY().toString(16);
String hexPrvKey = ecpriv.getS().toString(16);
// Get the hex representations we need.
String hexPubKey =
ecpub.getW().getAffineX().toString(16) + ecpub.getW().getAffineY().toString(16);
String hexPrvKey = ecpriv.getS().toString(16);
// In ethereum the private key is just 0x + private key, so nothing to do here.
Keccak256 keccak256 = new Keccak256();
byte[] addressData = keccak256.digest(HexBin.decode(hexPubKey));
String address = Hex.encodeHexString(addressData);
address = "0x" + address.substring(24);
// Return the address and the private key - we just store them for now.
return new String[] {address, hexPrvKey};
} catch (Exception e) {
return null;
}
// In ethereum the private key is just 0x + private key, so nothing to do here.
Keccak256 keccak256 = new Keccak256();
byte[] addressData = keccak256.digest(HexBin.decode(hexPubKey));
String address = Hex.encodeHexString(addressData);
address = "0x" + address.substring(24);
// Return the address and the private key - we just store them for now.
return new String[] {address, hexPrvKey};
}
}

20
pom.xml
View File

@ -33,6 +33,8 @@
<lombok.version>1.18.28</lombok.version>
<log4j.version>1.7.30</log4j.version>
<jupiter.api.version>5.7.0-M1</jupiter.api.version>
<mockito.version>5.10.0</mockito.version>
<mockito-inline.version>5.2.0</mockito-inline.version>
<tomcat.version>10.0.0-M5</tomcat.version>
<map.struct.version>1.3.0.Final</map.struct.version>
<maven.surefire.version>2.22.1</maven.surefire.version>
@ -93,6 +95,24 @@
<version>${jupiter.api.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito-inline.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>