[#1] Define SDK main functional #1
28 changed files with 177 additions and 203 deletions
18
README.md
18
README.md
|
@ -21,18 +21,18 @@ neo-go wallet export -w <path_to_your_wallet> -d <address_from_p1>
|
||||||
### Container
|
### Container
|
||||||
orikik marked this conversation as resolved
Outdated
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
import info.FrostFS.sdk.enums.BasicAcl;
|
|
||||||
import info.FrostFS.sdk.dto.container.Container;
|
import info.FrostFS.sdk.dto.container.Container;
|
||||||
import info.FrostFS.sdk.dto.netmap.PlacementPolicy;
|
import info.FrostFS.sdk.dto.netmap.PlacementPolicy;
|
||||||
import info.FrostFS.sdk.dto.netmap.Replica;
|
import info.FrostFS.sdk.dto.netmap.Replica;
|
||||||
|
import info.FrostFS.sdk.enums.BasicAcl;
|
||||||
|
import info.FrostFS.sdk.jdo.ClientSettings;
|
||||||
import info.FrostFS.sdk.services.FrostFSClient;
|
import info.FrostFS.sdk.services.FrostFSClient;
|
||||||
|
|
||||||
public class ContainerExample {
|
public class ContainerExample {
|
||||||
|
|
||||||
public void example() {
|
public void example() {
|
||||||
Client client = new Client( < your_key >);
|
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
|
||||||
GrpcClient grpcClient = new GrpcClient( < your_host >);
|
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
|
||||||
FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client);
|
|
||||||
|
|
||||||
// Create container
|
// Create container
|
||||||
var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)});
|
var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)});
|
||||||
|
@ -58,6 +58,7 @@ import info.FrostFS.sdk.dto.container.ContainerId;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectAttribute;
|
import info.FrostFS.sdk.dto.object.ObjectAttribute;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFilter;
|
import info.FrostFS.sdk.dto.object.ObjectFilter;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
||||||
|
import info.FrostFS.sdk.jdo.PutObjectParameters;
|
||||||
import info.FrostFS.sdk.services.FrostFSClient;
|
import info.FrostFS.sdk.services.FrostFSClient;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -66,9 +67,8 @@ import java.io.IOException;
|
||||||
public class ObjectExample {
|
public class ObjectExample {
|
||||||
|
|
||||||
public void example() {
|
public void example() {
|
||||||
Client client = new Client( < your_key >);
|
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
|
||||||
GrpcClient grpcClient = new GrpcClient( < your_host >);
|
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
|
||||||
FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client);
|
|
||||||
|
|
||||||
// Put object
|
// Put object
|
||||||
info.FrostFS.sdk.dto.object.ObjectId objectId;
|
info.FrostFS.sdk.dto.object.ObjectId objectId;
|
||||||
|
@ -76,7 +76,9 @@ public class ObjectExample {
|
||||||
var cat = new ObjectHeader(
|
var cat = new ObjectHeader(
|
||||||
containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")}
|
containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")}
|
||||||
);
|
);
|
||||||
objectId = frostFSClient.putObject(cat, fis);
|
|
||||||
|
var params = new PutObjectParameters(cat, fis);
|
||||||
|
objectId = frostFSClient.putObject(params);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
package info.FrostFS.sdk;
|
|
||||||
|
|
||||||
import info.FrostFS.sdk.dto.container.Container;
|
|
||||||
import info.FrostFS.sdk.dto.container.ContainerId;
|
|
||||||
import info.FrostFS.sdk.enums.BasicAcl;
|
|
||||||
import info.FrostFS.sdk.enums.ObjectType;
|
|
||||||
import info.FrostFS.sdk.dto.netmap.PlacementPolicy;
|
|
||||||
import info.FrostFS.sdk.dto.netmap.Replica;
|
|
||||||
import info.FrostFS.sdk.dto.object.ObjectAttribute;
|
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
|
||||||
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
|
||||||
import info.FrostFS.sdk.dto.object.ObjectId;
|
|
||||||
import info.FrostFS.sdk.services.FrostFSClient;
|
|
||||||
import info.FrostFS.sdk.tools.ClientSettings;
|
|
||||||
import info.FrostFS.sdk.tools.PutObjectParameters;
|
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Main {
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
ClientSettings clientSettings = new ClientSettings("KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq", "http://localhost:8080");
|
|
||||||
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
|
|
||||||
/*
|
|
||||||
var res2 = frostFSClient.searchObjectsAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"));
|
|
||||||
*/
|
|
||||||
var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)});
|
|
||||||
var containerId = frostFSClient.createContainer(new Container(BasicAcl.PUBLIC_RW, placementPolicy));
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
FileInputStream file = null;
|
|
||||||
try {
|
|
||||||
file = new FileInputStream("/home/ori/Desktop/cat.jpg");
|
|
||||||
var cat = new ObjectHeader(containerId, ObjectType.REGULAR, Collections.singletonList(new ObjectAttribute("Filename", "cat3.jpg")));
|
|
||||||
|
|
||||||
var params = new PutObjectParameters(cat, file, false, 1024);
|
|
||||||
var tty = frostFSClient.putObject(params);
|
|
||||||
|
|
||||||
System.out.println(1);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var res = frostFSClient.searchObjects(containerId);
|
|
||||||
|
|
||||||
ObjectFrostFS res3 = frostFSClient
|
|
||||||
.getObject(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"), new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww"));
|
|
||||||
|
|
||||||
|
|
||||||
var ttttt = frostFSClient.getNetworkSettings();
|
|
||||||
Container container2 = frostFSClient.getContainer(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Container container = frostFSClient.getContainer(containerId);
|
|
||||||
List<ContainerId> containerIds = frostFSClient.listContainers();
|
|
||||||
/*
|
|
||||||
frostFSClient.deleteContainerAsync(containerId);
|
|
||||||
*/
|
|
||||||
containerIds = frostFSClient.listContainers();
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.FrostFS.sdk.constants;
|
||||||
|
|
||||||
|
public class CryptoConst {
|
||||||
|
public static final String SIGNATURE_ALGORITHM = "NONEwithECDSAinP1363Format";
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package info.FrostFS.sdk.tools;
|
package info.FrostFS.sdk.jdo;
|
||||||
|
|
||||||
import info.FrostFS.sdk.dto.OwnerId;
|
import info.FrostFS.sdk.dto.OwnerId;
|
||||||
import info.FrostFS.sdk.dto.Version;
|
import info.FrostFS.sdk.dto.Version;
|
|
@ -1,4 +1,4 @@
|
||||||
package info.FrostFS.sdk.tools;
|
package info.FrostFS.sdk.jdo;
|
||||||
|
|
||||||
import io.grpc.ChannelCredentials;
|
import io.grpc.ChannelCredentials;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
|
@ -1,4 +1,4 @@
|
||||||
package info.FrostFS.sdk.tools;
|
package info.FrostFS.sdk.jdo;
|
||||||
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.FrostFS.sdk.tools;
|
package info.FrostFS.sdk.jdo;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
|
@ -1,4 +1,4 @@
|
||||||
package info.FrostFS.sdk.tools;
|
package info.FrostFS.sdk.jdo;
|
||||||
|
|
||||||
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.FrostFS.sdk.services;
|
package info.FrostFS.sdk.services;
|
||||||
|
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
|
|
||||||
public class ContextAccessor {
|
public class ContextAccessor {
|
||||||
private final ClientEnvironment context;
|
private final ClientEnvironment context;
|
||||||
|
|
|
@ -1,29 +1,32 @@
|
||||||
package info.FrostFS.sdk.services;
|
package info.FrostFS.sdk.services;
|
||||||
|
|
||||||
import frostFS.session.Types;
|
import frostFS.session.Types;
|
||||||
import info.FrostFS.sdk.tools.ClientSettings;
|
|
||||||
import info.FrostFS.sdk.tools.PutObjectParameters;
|
|
||||||
import info.FrostFS.sdk.dto.container.Container;
|
|
||||||
import info.FrostFS.sdk.dto.container.ContainerId;
|
|
||||||
import info.FrostFS.sdk.dto.SessionToken;
|
import info.FrostFS.sdk.dto.SessionToken;
|
||||||
import info.FrostFS.sdk.dto.Version;
|
import info.FrostFS.sdk.dto.Version;
|
||||||
|
import info.FrostFS.sdk.dto.container.Container;
|
||||||
|
import info.FrostFS.sdk.dto.container.ContainerId;
|
||||||
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
|
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
|
||||||
import info.FrostFS.sdk.dto.netmap.NodeInfo;
|
import info.FrostFS.sdk.dto.netmap.NodeInfo;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFilter;
|
import info.FrostFS.sdk.dto.object.ObjectFilter;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectId;
|
import info.FrostFS.sdk.dto.object.ObjectId;
|
||||||
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
|
import info.FrostFS.sdk.jdo.ClientSettings;
|
||||||
|
import info.FrostFS.sdk.jdo.NetworkSettings;
|
||||||
|
import info.FrostFS.sdk.jdo.PutObjectParameters;
|
||||||
import info.FrostFS.sdk.services.impl.*;
|
import info.FrostFS.sdk.services.impl.*;
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
|
||||||
import info.FrostFS.sdk.tools.NetworkSettings;
|
|
||||||
import io.grpc.Channel;
|
import io.grpc.Channel;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static info.FrostFS.sdk.GrpcClient.initGrpcChannel;
|
import static info.FrostFS.sdk.tools.GrpcClient.initGrpcChannel;
|
||||||
import static java.util.Objects.isNull;
|
import static java.util.Objects.isNull;
|
||||||
|
|
||||||
public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient {
|
public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient {
|
||||||
|
private static final String ERROR_CLIENT_OPTIONS_INIT = "Options must be initialized.";
|
||||||
|
private static final String ERROR_VERSION_SUPPORT_TEMPLATE = "FrostFS %s is not supported.";
|
||||||
|
|
||||||
private final ContainerService containerService;
|
private final ContainerService containerService;
|
||||||
private final NetmapService netmapService;
|
private final NetmapService netmapService;
|
||||||
private final ObjectService objectService;
|
private final ObjectService objectService;
|
||||||
|
@ -32,7 +35,7 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
|
||||||
|
|
||||||
public FrostFSClient(ClientSettings clientSettings) {
|
public FrostFSClient(ClientSettings clientSettings) {
|
||||||
if (isNull(clientSettings)) {
|
if (isNull(clientSettings)) {
|
||||||
throw new IllegalArgumentException("Options must be initialized");
|
throw new IllegalArgumentException(ERROR_CLIENT_OPTIONS_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
clientSettings.validate();
|
clientSettings.validate();
|
||||||
|
@ -53,9 +56,9 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
|
||||||
private void checkFrostFsVersionSupport(Version version) {
|
private void checkFrostFsVersionSupport(Version version) {
|
||||||
var localNodeInfo = netmapService.getLocalNodeInfo();
|
var localNodeInfo = netmapService.getLocalNodeInfo();
|
||||||
if (!localNodeInfo.getVersion().isSupported(version)) {
|
if (!localNodeInfo.getVersion().isSupported(version)) {
|
||||||
var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion());
|
throw new IllegalArgumentException(
|
||||||
System.out.println(msg);
|
String.format(ERROR_VERSION_SUPPORT_TEMPLATE, localNodeInfo.getVersion())
|
||||||
throw new IllegalArgumentException(msg);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package info.FrostFS.sdk.services;
|
||||||
|
|
||||||
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
|
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
|
||||||
import info.FrostFS.sdk.dto.netmap.NodeInfo;
|
import info.FrostFS.sdk.dto.netmap.NodeInfo;
|
||||||
import info.FrostFS.sdk.tools.NetworkSettings;
|
import info.FrostFS.sdk.jdo.NetworkSettings;
|
||||||
|
|
||||||
public interface NetmapClient {
|
public interface NetmapClient {
|
||||||
NetmapSnapshot getNetmapSnapshot();
|
NetmapSnapshot getNetmapSnapshot();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package info.FrostFS.sdk.services;
|
package info.FrostFS.sdk.services;
|
||||||
|
|
||||||
import info.FrostFS.sdk.dto.container.ContainerId;
|
import info.FrostFS.sdk.dto.container.ContainerId;
|
||||||
import info.FrostFS.sdk.tools.PutObjectParameters;
|
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFilter;
|
import info.FrostFS.sdk.dto.object.ObjectFilter;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectId;
|
import info.FrostFS.sdk.dto.object.ObjectId;
|
||||||
|
import info.FrostFS.sdk.jdo.PutObjectParameters;
|
||||||
|
|
||||||
public interface ObjectClient {
|
public interface ObjectClient {
|
||||||
ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId);
|
ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId);
|
||||||
|
|
|
@ -2,23 +2,23 @@ package info.FrostFS.sdk.services.impl;
|
||||||
|
|
||||||
import frostFS.container.ContainerServiceGrpc;
|
import frostFS.container.ContainerServiceGrpc;
|
||||||
import frostFS.container.Service;
|
import frostFS.container.Service;
|
||||||
import info.FrostFS.sdk.Verifier;
|
|
||||||
import info.FrostFS.sdk.dto.container.Container;
|
import info.FrostFS.sdk.dto.container.Container;
|
||||||
import info.FrostFS.sdk.dto.container.ContainerId;
|
import info.FrostFS.sdk.dto.container.ContainerId;
|
||||||
import info.FrostFS.sdk.mappers.container.ContainerIdMapper;
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
import info.FrostFS.sdk.mappers.container.ContainerMapper;
|
|
||||||
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
||||||
import info.FrostFS.sdk.mappers.VersionMapper;
|
import info.FrostFS.sdk.mappers.VersionMapper;
|
||||||
|
import info.FrostFS.sdk.mappers.container.ContainerIdMapper;
|
||||||
|
import info.FrostFS.sdk.mappers.container.ContainerMapper;
|
||||||
import info.FrostFS.sdk.services.ContainerClient;
|
import info.FrostFS.sdk.services.ContainerClient;
|
||||||
import info.FrostFS.sdk.services.ContextAccessor;
|
import info.FrostFS.sdk.services.ContextAccessor;
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
import info.FrostFS.sdk.tools.Verifier;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
|
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
|
||||||
import static info.FrostFS.sdk.RequestSigner.sign;
|
import static info.FrostFS.sdk.tools.RequestSigner.sign;
|
||||||
import static info.FrostFS.sdk.RequestSigner.signRFC6979;
|
import static info.FrostFS.sdk.tools.RequestSigner.signRFC6979;
|
||||||
|
|
||||||
public class ContainerService extends ContextAccessor implements ContainerClient {
|
public class ContainerService extends ContextAccessor implements ContainerClient {
|
||||||
private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;
|
private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;
|
||||||
|
|
|
@ -3,20 +3,20 @@ package info.FrostFS.sdk.services.impl;
|
||||||
import frostFS.netmap.NetmapServiceGrpc;
|
import frostFS.netmap.NetmapServiceGrpc;
|
||||||
import frostFS.netmap.Service;
|
import frostFS.netmap.Service;
|
||||||
import frostFS.netmap.Types;
|
import frostFS.netmap.Types;
|
||||||
import info.FrostFS.sdk.Verifier;
|
|
||||||
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
|
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
|
||||||
import info.FrostFS.sdk.dto.netmap.NodeInfo;
|
import info.FrostFS.sdk.dto.netmap.NodeInfo;
|
||||||
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
|
import info.FrostFS.sdk.jdo.NetworkSettings;
|
||||||
import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper;
|
import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper;
|
||||||
import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper;
|
import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper;
|
||||||
import info.FrostFS.sdk.services.ContextAccessor;
|
import info.FrostFS.sdk.services.ContextAccessor;
|
||||||
import info.FrostFS.sdk.services.NetmapClient;
|
import info.FrostFS.sdk.services.NetmapClient;
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
import info.FrostFS.sdk.tools.Verifier;
|
||||||
import info.FrostFS.sdk.tools.NetworkSettings;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
|
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
|
||||||
import static info.FrostFS.sdk.RequestSigner.sign;
|
import static info.FrostFS.sdk.tools.RequestSigner.sign;
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
|
|
||||||
public class NetmapService extends ContextAccessor implements NetmapClient {
|
public class NetmapService extends ContextAccessor implements NetmapClient {
|
||||||
|
|
|
@ -2,11 +2,14 @@ package info.FrostFS.sdk.services.impl;
|
||||||
|
|
||||||
import frostFS.object.Service;
|
import frostFS.object.Service;
|
||||||
import frostFS.object.Types;
|
import frostFS.object.Types;
|
||||||
import info.FrostFS.sdk.Verifier;
|
import info.FrostFS.sdk.tools.Verifier;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class ObjectReader {
|
public class ObjectReader {
|
||||||
|
public static final String ERROR_UNEXPECTED_STREAM = "unexpected end of stream";
|
||||||
|
public static final String ERROR_UNEXPECTED_MESSAGE_TYPE = "unexpected message type";
|
||||||
|
|
||||||
public Iterator<Service.GetResponse> call;
|
public Iterator<Service.GetResponse> call;
|
||||||
|
|
||||||
public ObjectReader(Iterator<Service.GetResponse> call) {
|
public ObjectReader(Iterator<Service.GetResponse> call) {
|
||||||
|
@ -15,14 +18,14 @@ public class ObjectReader {
|
||||||
|
|
||||||
public Types.Object readHeader() {
|
public Types.Object readHeader() {
|
||||||
if (!call.hasNext()) {
|
if (!call.hasNext()) {
|
||||||
throw new IllegalArgumentException("unexpected end of stream");
|
throw new IllegalArgumentException(ERROR_UNEXPECTED_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = call.next();
|
var response = call.next();
|
||||||
Verifier.checkResponse(response);
|
Verifier.checkResponse(response);
|
||||||
|
|
||||||
if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.INIT_FIELD_NUMBER) {
|
if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.INIT_FIELD_NUMBER) {
|
||||||
throw new IllegalArgumentException("unexpected message type");
|
throw new IllegalArgumentException(ERROR_UNEXPECTED_MESSAGE_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Types.Object.newBuilder()
|
return Types.Object.newBuilder()
|
||||||
|
@ -40,7 +43,7 @@ public class ObjectReader {
|
||||||
Verifier.checkResponse(response);
|
Verifier.checkResponse(response);
|
||||||
|
|
||||||
if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.CHUNK_FIELD_NUMBER) {
|
if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.CHUNK_FIELD_NUMBER) {
|
||||||
throw new IllegalArgumentException("unexpected message type");
|
throw new IllegalArgumentException(ERROR_UNEXPECTED_MESSAGE_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.getBody().getChunk().toByteArray();
|
return response.getBody().getChunk().toByteArray();
|
||||||
|
|
|
@ -5,21 +5,22 @@ import com.google.protobuf.ByteString;
|
||||||
import frostFS.object.ObjectServiceGrpc;
|
import frostFS.object.ObjectServiceGrpc;
|
||||||
import frostFS.object.Service;
|
import frostFS.object.Service;
|
||||||
import frostFS.refs.Types;
|
import frostFS.refs.Types;
|
||||||
import info.FrostFS.sdk.Verifier;
|
|
||||||
import info.FrostFS.sdk.constants.AppConst;
|
import info.FrostFS.sdk.constants.AppConst;
|
||||||
import info.FrostFS.sdk.dto.container.ContainerId;
|
|
||||||
import info.FrostFS.sdk.dto.Split;
|
import info.FrostFS.sdk.dto.Split;
|
||||||
|
import info.FrostFS.sdk.dto.container.ContainerId;
|
||||||
import info.FrostFS.sdk.dto.object.*;
|
import info.FrostFS.sdk.dto.object.*;
|
||||||
import info.FrostFS.sdk.mappers.*;
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
|
import info.FrostFS.sdk.jdo.PutObjectParameters;
|
||||||
|
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
||||||
|
import info.FrostFS.sdk.mappers.VersionMapper;
|
||||||
import info.FrostFS.sdk.mappers.container.ContainerIdMapper;
|
import info.FrostFS.sdk.mappers.container.ContainerIdMapper;
|
||||||
import info.FrostFS.sdk.mappers.object.ObjectFilterMapper;
|
import info.FrostFS.sdk.mappers.object.ObjectFilterMapper;
|
||||||
|
import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper;
|
||||||
import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper;
|
import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper;
|
||||||
import info.FrostFS.sdk.mappers.object.ObjectIdMapper;
|
import info.FrostFS.sdk.mappers.object.ObjectIdMapper;
|
||||||
import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper;
|
|
||||||
import info.FrostFS.sdk.services.ContextAccessor;
|
import info.FrostFS.sdk.services.ContextAccessor;
|
||||||
import info.FrostFS.sdk.services.ObjectClient;
|
import info.FrostFS.sdk.services.ObjectClient;
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
import info.FrostFS.sdk.tools.Verifier;
|
||||||
import info.FrostFS.sdk.tools.PutObjectParameters;
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -29,12 +30,14 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static info.FrostFS.sdk.Helper.getSha256;
|
import static info.FrostFS.sdk.Helper.getSha256;
|
||||||
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
|
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
|
||||||
import static info.FrostFS.sdk.RequestConstructor.addObjectSessionToken;
|
import static info.FrostFS.sdk.tools.RequestConstructor.addObjectSessionToken;
|
||||||
import static info.FrostFS.sdk.RequestSigner.sign;
|
import static info.FrostFS.sdk.tools.RequestSigner.sign;
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
|
|
||||||
public class ObjectService extends ContextAccessor implements ObjectClient {
|
public class ObjectService extends ContextAccessor implements ObjectClient {
|
||||||
|
private static final String ERROR_PAYLOAD = "PayloadLength must be specified";
|
||||||
|
|
||||||
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
|
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
|
||||||
private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient;
|
private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient;
|
||||||
private final ObjectTools objectTools;
|
private final ObjectTools objectTools;
|
||||||
|
@ -257,7 +260,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient {
|
||||||
var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize());
|
var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize());
|
||||||
var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength();
|
var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength();
|
||||||
if (fullLength == 0) {
|
if (fullLength == 0) {
|
||||||
throw new IllegalArgumentException("Payload stream must be able to seek or PayloadLength must be specified");
|
throw new IllegalArgumentException(ERROR_PAYLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer = new byte[objectSize];
|
var buffer = new byte[objectSize];
|
||||||
|
|
|
@ -5,17 +5,17 @@ import frostFS.object.Types;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
import info.FrostFS.sdk.dto.object.ObjectFrostFS;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
import info.FrostFS.sdk.dto.object.ObjectHeader;
|
||||||
import info.FrostFS.sdk.dto.object.ObjectId;
|
import info.FrostFS.sdk.dto.object.ObjectId;
|
||||||
import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper;
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
import info.FrostFS.sdk.mappers.object.ObjectIdMapper;
|
|
||||||
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
||||||
import info.FrostFS.sdk.mappers.VersionMapper;
|
import info.FrostFS.sdk.mappers.VersionMapper;
|
||||||
|
import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper;
|
||||||
|
import info.FrostFS.sdk.mappers.object.ObjectIdMapper;
|
||||||
import info.FrostFS.sdk.services.ContextAccessor;
|
import info.FrostFS.sdk.services.ContextAccessor;
|
||||||
import info.FrostFS.sdk.services.ToolsClient;
|
import info.FrostFS.sdk.services.ToolsClient;
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
|
||||||
import org.apache.commons.collections4.ListUtils;
|
import org.apache.commons.collections4.ListUtils;
|
||||||
|
|
||||||
import static info.FrostFS.sdk.Helper.getSha256;
|
import static info.FrostFS.sdk.Helper.getSha256;
|
||||||
import static info.FrostFS.sdk.RequestSigner.signData;
|
import static info.FrostFS.sdk.tools.RequestSigner.signData;
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
|
|
||||||
public class ObjectTools extends ContextAccessor implements ToolsClient {
|
public class ObjectTools extends ContextAccessor implements ToolsClient {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.FrostFS.sdk.services.impl;
|
package info.FrostFS.sdk.services.impl;
|
||||||
|
|
||||||
import frostFS.object.Service;
|
import frostFS.object.Service;
|
||||||
import info.FrostFS.sdk.Verifier;
|
import info.FrostFS.sdk.tools.Verifier;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -4,14 +4,14 @@ import frostFS.session.Service;
|
||||||
import frostFS.session.SessionServiceGrpc;
|
import frostFS.session.SessionServiceGrpc;
|
||||||
import frostFS.session.Types;
|
import frostFS.session.Types;
|
||||||
import info.FrostFS.sdk.dto.SessionToken;
|
import info.FrostFS.sdk.dto.SessionToken;
|
||||||
|
import info.FrostFS.sdk.jdo.ClientEnvironment;
|
||||||
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
import info.FrostFS.sdk.mappers.OwnerIdMapper;
|
||||||
import info.FrostFS.sdk.mappers.SessionMapper;
|
import info.FrostFS.sdk.mappers.SessionMapper;
|
||||||
import info.FrostFS.sdk.services.ContextAccessor;
|
import info.FrostFS.sdk.services.ContextAccessor;
|
||||||
import info.FrostFS.sdk.services.SessionClient;
|
import info.FrostFS.sdk.services.SessionClient;
|
||||||
import info.FrostFS.sdk.tools.ClientEnvironment;
|
|
||||||
|
|
||||||
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
|
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
|
||||||
import static info.FrostFS.sdk.RequestSigner.sign;
|
import static info.FrostFS.sdk.tools.RequestSigner.sign;
|
||||||
|
|
||||||
public class SessionService extends ContextAccessor implements SessionClient {
|
public class SessionService extends ContextAccessor implements SessionClient {
|
||||||
private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub;
|
private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.FrostFS.sdk;
|
package info.FrostFS.sdk.tools;
|
||||||
|
|
||||||
import io.grpc.Channel;
|
import io.grpc.Channel;
|
||||||
import io.grpc.ChannelCredentials;
|
import io.grpc.ChannelCredentials;
|
||||||
|
@ -10,6 +10,7 @@ import java.net.URISyntaxException;
|
||||||
import static java.util.Objects.isNull;
|
import static java.util.Objects.isNull;
|
||||||
|
|
||||||
public class GrpcClient {
|
public class GrpcClient {
|
||||||
|
private static final String ERROR_INVALID_HOST_TEMPLATE = "Host %s has invalid format. Error: %s";
|
||||||
|
|
||||||
public static Channel initGrpcChannel(String host, ChannelCredentials creds) {
|
public static Channel initGrpcChannel(String host, ChannelCredentials creds) {
|
||||||
try {
|
try {
|
||||||
|
@ -19,8 +20,7 @@ public class GrpcClient {
|
||||||
|
|
||||||
return channelBuilder.usePlaintext().build();
|
return channelBuilder.usePlaintext().build();
|
||||||
} catch (URISyntaxException exp) {
|
} catch (URISyntaxException exp) {
|
||||||
var message = String.format("Host %s has invalid format. Error: %s", host, exp.getMessage());
|
throw new IllegalArgumentException(String.format(ERROR_INVALID_HOST_TEMPLATE, host, exp.getMessage()));
|
||||||
throw new IllegalArgumentException(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.FrostFS.sdk.tools;
|
||||||
|
|
||||||
|
import com.google.protobuf.Message;
|
||||||
|
import com.google.protobuf.MessageOrBuilder;
|
||||||
|
|
||||||
|
public class MessageHelper {
|
||||||
|
|
||||||
|
public static Message getField(MessageOrBuilder messageOrBuilder, String fieldName) {
|
||||||
|
return (Message) messageOrBuilder.getField(messageOrBuilder.getDescriptorForType().findFieldByName(fieldName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setField(Message.Builder builder, String fieldName, Object value) {
|
||||||
|
builder.setField(builder.getDescriptorForType().findFieldByName(fieldName), value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +1,37 @@
|
||||||
package info.FrostFS.sdk;
|
package info.FrostFS.sdk.tools;
|
||||||
|
|
||||||
import com.google.protobuf.AbstractMessage;
|
import com.google.protobuf.Message;
|
||||||
import frostFS.session.Types;
|
import frostFS.session.Types;
|
||||||
import info.FrostFS.sdk.dto.MetaHeader;
|
import info.FrostFS.sdk.dto.MetaHeader;
|
||||||
|
import info.FrostFS.sdk.jdo.ECDsa;
|
||||||
import info.FrostFS.sdk.mappers.MetaHeaderMapper;
|
import info.FrostFS.sdk.mappers.MetaHeaderMapper;
|
||||||
import info.FrostFS.sdk.tools.ECDsa;
|
|
||||||
|
|
||||||
import static info.FrostFS.sdk.RequestSigner.signMessagePart;
|
import static info.FrostFS.sdk.constants.FieldConst.META_HEADER_FIELD_NAME;
|
||||||
|
import static info.FrostFS.sdk.tools.MessageHelper.getField;
|
||||||
|
import static info.FrostFS.sdk.tools.MessageHelper.setField;
|
||||||
|
import static info.FrostFS.sdk.tools.RequestSigner.signMessagePart;
|
||||||
import static java.util.Objects.isNull;
|
import static java.util.Objects.isNull;
|
||||||
|
|
||||||
public class RequestConstructor {
|
public class RequestConstructor {
|
||||||
|
|
||||||
public static void addMetaHeader(AbstractMessage.Builder request) {
|
public static void addMetaHeader(Message.Builder request) {
|
||||||
addMetaHeader(request, null);
|
addMetaHeader(request, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addMetaHeader(AbstractMessage.Builder request, Types.RequestMetaHeader metaHeader) {
|
public static void addMetaHeader(Message.Builder request, Types.RequestMetaHeader metaHeader) {
|
||||||
if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) {
|
if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) {
|
||||||
metaHeader = MetaHeaderMapper.toGrpcMessage(MetaHeader.getDefault());
|
metaHeader = MetaHeaderMapper.toGrpcMessage(MetaHeader.getDefault());
|
||||||
var field = request.getDescriptorForType().findFieldByName("meta_header");
|
setField(request, META_HEADER_FIELD_NAME, metaHeader);
|
||||||
request.setField(field, metaHeader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addObjectSessionToken(AbstractMessage.Builder request,
|
public static void addObjectSessionToken(Message.Builder request,
|
||||||
Types.SessionToken sessionToken,
|
Types.SessionToken sessionToken,
|
||||||
frostFS.refs.Types.ContainerID cid,
|
frostFS.refs.Types.ContainerID cid,
|
||||||
frostFS.refs.Types.ObjectID oid,
|
frostFS.refs.Types.ObjectID oid,
|
||||||
Types.ObjectSessionContext.Verb verb,
|
Types.ObjectSessionContext.Verb verb,
|
||||||
ECDsa key) {
|
ECDsa key) {
|
||||||
var headerField = request.getDescriptorForType().findFieldByName("meta_header");
|
var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME);
|
||||||
var header = (Types.RequestMetaHeader) request.getField(headerField);
|
|
||||||
if (header.getSessionToken().getSerializedSize() > 0) {
|
if (header.getSessionToken().getSerializedSize() > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +47,6 @@ public class RequestConstructor {
|
||||||
.setBody(body)
|
.setBody(body)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
request.setField(headerField, header.toBuilder().setSessionToken(sessionToken).build());
|
setField(request, META_HEADER_FIELD_NAME, header.toBuilder().setSessionToken(sessionToken).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package info.FrostFS.sdk;
|
package info.FrostFS.sdk.tools;
|
||||||
|
|
||||||
import com.google.protobuf.AbstractMessage;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.Message;
|
||||||
import frostFS.session.Types;
|
import frostFS.session.Types;
|
||||||
import info.FrostFS.sdk.tools.ECDsa;
|
import info.FrostFS.sdk.jdo.ECDsa;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
||||||
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
|
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
|
||||||
|
@ -15,17 +15,22 @@ import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
|
||||||
|
import static info.FrostFS.sdk.constants.CryptoConst.SIGNATURE_ALGORITHM;
|
||||||
|
import static info.FrostFS.sdk.constants.FieldConst.*;
|
||||||
|
import static info.FrostFS.sdk.tools.MessageHelper.getField;
|
||||||
|
import static info.FrostFS.sdk.tools.MessageHelper.setField;
|
||||||
import static org.bouncycastle.crypto.util.DigestFactory.createSHA256;
|
import static org.bouncycastle.crypto.util.DigestFactory.createSHA256;
|
||||||
import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray;
|
import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray;
|
||||||
|
|
||||||
public class RequestSigner {
|
public class RequestSigner {
|
||||||
|
public static final String ERROR_UNSUPPORTED_TYPE_TEMPLATE = "Unsupported message type: %s";
|
||||||
public static final int RFC6979_SIGNATURE_SIZE = 64;
|
public static final int RFC6979_SIGNATURE_SIZE = 64;
|
||||||
|
|
||||||
public static byte[] signData(ECDsa key, byte[] data) {
|
public static byte[] signData(ECDsa key, byte[] data) {
|
||||||
var hash = new byte[65];
|
var hash = new byte[65];
|
||||||
hash[0] = 0x04;
|
hash[0] = 0x04;
|
||||||
try {
|
try {
|
||||||
Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format");
|
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
|
||||||
signature.initSign(key.getPrivateKey());
|
signature.initSign(key.getPrivateKey());
|
||||||
signature.update(DigestUtils.sha512(data));
|
signature.update(DigestUtils.sha512(data));
|
||||||
byte[] sig = signature.sign();
|
byte[] sig = signature.sign();
|
||||||
|
@ -62,7 +67,7 @@ public class RequestSigner {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, AbstractMessage message) {
|
public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, Message message) {
|
||||||
return frostFS.refs.Types.SignatureRFC6979.newBuilder()
|
return frostFS.refs.Types.SignatureRFC6979.newBuilder()
|
||||||
.setKey(ByteString.copyFrom(key.getPublicKeyByte()))
|
.setKey(ByteString.copyFrom(key.getPublicKeyByte()))
|
||||||
.setSign(ByteString.copyFrom(signRFC6979(key, message.toByteArray())))
|
.setSign(ByteString.copyFrom(signRFC6979(key, message.toByteArray())))
|
||||||
|
@ -76,7 +81,7 @@ public class RequestSigner {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static frostFS.refs.Types.Signature signMessagePart(ECDsa key, AbstractMessage data) {
|
public static frostFS.refs.Types.Signature signMessagePart(ECDsa key, Message data) {
|
||||||
var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray();
|
var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray();
|
||||||
return frostFS.refs.Types.Signature.newBuilder()
|
return frostFS.refs.Types.Signature.newBuilder()
|
||||||
.setKey(ByteString.copyFrom(key.getPublicKeyByte()))
|
.setKey(ByteString.copyFrom(key.getPublicKeyByte()))
|
||||||
|
@ -84,39 +89,32 @@ public class RequestSigner {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sign(AbstractMessage.Builder request, ECDsa key) {
|
public static void sign(Message.Builder request, ECDsa key) {
|
||||||
var meta = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("meta_header"));
|
var meta = getField(request, META_HEADER_FIELD_NAME);
|
||||||
var body = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("body"));
|
var body = getField(request, BODY_FIELD_NAME);
|
||||||
var verify = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("verify_header"));
|
var verify = getField(request, VERIFY_HEADER_FIELD_NAME);
|
||||||
|
var verifyOrigin = getField(verify, ORIGIN_FIELD_NAME);
|
||||||
|
|
||||||
AbstractMessage.Builder verifyBuilder;
|
Message.Builder verifyBuilder;
|
||||||
if (verify instanceof Types.RequestVerificationHeader) {
|
if (verify instanceof Types.RequestVerificationHeader) {
|
||||||
verifyBuilder = Types.RequestVerificationHeader.newBuilder();
|
verifyBuilder = Types.RequestVerificationHeader.newBuilder();
|
||||||
} else if (verify instanceof Types.ResponseVerificationHeader) {
|
} else if (verify instanceof Types.ResponseVerificationHeader) {
|
||||||
verifyBuilder = Types.ResponseVerificationHeader.newBuilder();
|
verifyBuilder = Types.ResponseVerificationHeader.newBuilder();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unsopported message type");
|
throw new IllegalArgumentException(
|
||||||
|
String.format(ERROR_UNSUPPORTED_TYPE_TEMPLATE, verify.getClass().getName())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var verifyOrigin = (AbstractMessage) verify.getField(verify.getDescriptorForType().findFieldByName("origin"));
|
|
||||||
if (verifyOrigin.getSerializedSize() == 0) {
|
if (verifyOrigin.getSerializedSize() == 0) {
|
||||||
verifyBuilder.setField(
|
setField(verifyBuilder, BODY_SIGNATURE_FIELD_NAME, signMessagePart(key, body));
|
||||||
verifyBuilder.getDescriptorForType().findFieldByName("body_signature"),
|
|
||||||
signMessagePart(key, body)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin);
|
setField(verifyBuilder, ORIGIN_FIELD_NAME, verifyOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyBuilder.setField(
|
setField(verifyBuilder, META_SIGNATURE_FIELD_NAME, signMessagePart(key, meta));
|
||||||
verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"),
|
setField(verifyBuilder, ORIGIN_SIGNATURE_FIELD_NAME, signMessagePart(key, verifyOrigin));
|
||||||
signMessagePart(key, meta)
|
setField(request, VERIFY_HEADER_FIELD_NAME, verifyBuilder.build());
|
||||||
);
|
}
|
||||||
verifyBuilder.setField(
|
|
||||||
verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"),
|
|
||||||
signMessagePart(key, verifyOrigin)
|
|
||||||
);
|
|
||||||
|
|
||||||
request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build());
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package info.FrostFS.sdk;
|
package info.FrostFS.sdk.tools;
|
||||||
|
|
||||||
import com.google.protobuf.AbstractMessage;
|
import com.google.protobuf.Message;
|
||||||
import frostFS.refs.Types;
|
import frostFS.session.Types;
|
||||||
import info.FrostFS.sdk.mappers.StatusMapper;
|
import info.FrostFS.sdk.mappers.StatusMapper;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
||||||
|
@ -17,17 +17,20 @@ import java.security.Signature;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static info.FrostFS.sdk.KeyExtension.getPublicKeyFromBytes;
|
import static info.FrostFS.sdk.KeyExtension.getPublicKeyFromBytes;
|
||||||
|
import static info.FrostFS.sdk.constants.CryptoConst.SIGNATURE_ALGORITHM;
|
||||||
|
import static info.FrostFS.sdk.constants.FieldConst.*;
|
||||||
|
import static info.FrostFS.sdk.tools.MessageHelper.getField;
|
||||||
import static java.util.Objects.isNull;
|
import static java.util.Objects.isNull;
|
||||||
import static org.bouncycastle.crypto.util.DigestFactory.createSHA256;
|
import static org.bouncycastle.crypto.util.DigestFactory.createSHA256;
|
||||||
import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray;
|
import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray;
|
||||||
|
|
||||||
public class Verifier {
|
public class Verifier {
|
||||||
|
public static final String ERROR_WRONG_SIG_SIZE_TEMPLATE = "Wrong signature size. Expected length=%s, actual=%s";
|
||||||
|
public static final String ERROR_INVALID_RESPONSE = "Invalid response";
|
||||||
public static final int RFC6979_SIG_SIZE = 64;
|
public static final int RFC6979_SIG_SIZE = 64;
|
||||||
|
|
||||||
public static boolean verifyRFC6979(Types.SignatureRFC6979 signature, AbstractMessage message) {
|
public static boolean verifyRFC6979(frostFS.refs.Types.SignatureRFC6979 signature, Message data) {
|
||||||
return verifyRFC6979(
|
return verifyRFC6979(signature.getKey().toByteArray(), data.toByteArray(), signature.getSign().toByteArray());
|
||||||
signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) {
|
public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) {
|
||||||
|
@ -49,8 +52,7 @@ public class Verifier {
|
||||||
private static BigInteger[] decodeSignature(byte[] sig) {
|
private static BigInteger[] decodeSignature(byte[] sig) {
|
||||||
if (sig.length != RFC6979_SIG_SIZE) {
|
if (sig.length != RFC6979_SIG_SIZE) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Wrong signature size. Expected length=%s, actual=%s",
|
String.format(ERROR_WRONG_SIG_SIZE_TEMPLATE, RFC6979_SIG_SIZE, sig.length)
|
||||||
RFC6979_SIG_SIZE, sig.length)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,42 +63,40 @@ public class Verifier {
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkResponse(AbstractMessage response) {
|
public static void checkResponse(Message response) {
|
||||||
if (!verify(response)) {
|
if (!verify(response)) {
|
||||||
throw new IllegalArgumentException("Invalid response");
|
throw new IllegalArgumentException(ERROR_INVALID_RESPONSE);
|
||||||
}
|
}
|
||||||
var metaHeader = (frostFS.session.Types.ResponseMetaHeader) response
|
|
||||||
.getField(response.getDescriptorForType().findFieldByName("meta_header"));
|
var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME);
|
||||||
var status = StatusMapper.toModel(metaHeader.getStatus());
|
var status = StatusMapper.toModel(metaHeader.getStatus());
|
||||||
if (!status.isSuccess()) {
|
if (!status.isSuccess()) {
|
||||||
throw new IllegalArgumentException(status.toString());
|
throw new IllegalArgumentException(status.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verify(AbstractMessage message) {
|
public static boolean verify(Message response) {
|
||||||
var body = (AbstractMessage) message.getField(message.getDescriptorForType().findFieldByName("body"));
|
var body = getField(response, BODY_FIELD_NAME);
|
||||||
var metaHeader = (frostFS.session.Types.ResponseMetaHeader)
|
var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME);
|
||||||
message.getField(message.getDescriptorForType().findFieldByName("meta_header"));
|
var verifyHeader = (Types.ResponseVerificationHeader) getField(response, VERIFY_HEADER_FIELD_NAME);
|
||||||
var verifyHeader = (frostFS.session.Types.ResponseVerificationHeader)
|
|
||||||
message.getField(message.getDescriptorForType().findFieldByName("verify_header"));
|
|
||||||
|
|
||||||
return verifyMatryoshkaLevel(body, metaHeader, verifyHeader);
|
return verifyMatryoshkaLevel(body, metaHeader, verifyHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verifyMatryoshkaLevel(AbstractMessage body,
|
public static boolean verifyMatryoshkaLevel(Message data,
|
||||||
frostFS.session.Types.ResponseMetaHeader meta,
|
frostFS.session.Types.ResponseMetaHeader meta,
|
||||||
frostFS.session.Types.ResponseVerificationHeader verification) {
|
frostFS.session.Types.ResponseVerificationHeader verification) {
|
||||||
if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false;
|
if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false;
|
||||||
var origin = verification.getOrigin();
|
var origin = verification.getOrigin();
|
||||||
if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false;
|
if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false;
|
||||||
if (origin.getSerializedSize() == 0) {
|
if (origin.getSerializedSize() == 0) {
|
||||||
return verifyMessagePart(verification.getBodySignature(), body);
|
return verifyMessagePart(verification.getBodySignature(), data);
|
||||||
}
|
}
|
||||||
return verification.getBodySignature().getSerializedSize() == 0
|
return verification.getBodySignature().getSerializedSize() == 0
|
||||||
&& verifyMatryoshkaLevel(body, meta.getOrigin(), origin);
|
&& verifyMatryoshkaLevel(data, meta.getOrigin(), origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verifyMessagePart(Types.Signature sig, AbstractMessage data) {
|
public static boolean verifyMessagePart(frostFS.refs.Types.Signature sig, Message data) {
|
||||||
if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false;
|
if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false;
|
||||||
|
|
||||||
var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray());
|
var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray());
|
||||||
|
@ -107,7 +107,7 @@ public class Verifier {
|
||||||
|
|
||||||
public static boolean verifyData(PublicKey publicKey, byte[] data, byte[] sig) {
|
public static boolean verifyData(PublicKey publicKey, byte[] data, byte[] sig) {
|
||||||
try {
|
try {
|
||||||
Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format");
|
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
|
||||||
signature.initVerify(publicKey);
|
signature.initVerify(publicKey);
|
||||||
signature.update(DigestUtils.sha512(data));
|
signature.update(DigestUtils.sha512(data));
|
||||||
return signature.verify(Arrays.copyOfRange(sig, 1, sig.length));
|
return signature.verify(Arrays.copyOfRange(sig, 1, sig.length));
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.FrostFS.sdk;
|
package info.FrostFS.sdk;
|
||||||
|
|
||||||
import com.google.protobuf.AbstractMessage;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.Message;
|
||||||
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
|
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
@ -30,7 +30,7 @@ public class Helper {
|
||||||
return getSha256Instance().digest(value);
|
return getSha256Instance().digest(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteString getSha256(AbstractMessage value) {
|
public static ByteString getSha256(Message value) {
|
||||||
return ByteString.copyFrom(getSha256(value.toByteArray()));
|
return ByteString.copyFrom(getSha256(value.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package info.FrostFS.sdk.constants;
|
||||||
|
|
||||||
|
public class FieldConst {
|
||||||
|
public static final String META_HEADER_FIELD_NAME = "meta_header";
|
||||||
|
public static final String META_SIGNATURE_FIELD_NAME = "meta_signature";
|
||||||
|
public static final String BODY_FIELD_NAME = "body";
|
||||||
|
public static final String BODY_SIGNATURE_FIELD_NAME = "body_signature";
|
||||||
|
public static final String ORIGIN_FIELD_NAME = "origin";
|
||||||
|
public static final String ORIGIN_SIGNATURE_FIELD_NAME = "origin_signature";
|
||||||
|
public static final String VERIFY_HEADER_FIELD_NAME = "verify_header";
|
||||||
|
}
|
Loading…
Reference in a new issue
Container operations maybe?
agree, corrected