[#1] Define SDK main functional #1

Merged
orikik merged 7 commits from orikik/frostfs-sdk-java:master into master 2024-09-04 19:51:24 +00:00
28 changed files with 177 additions and 203 deletions
Showing only changes of commit a7fab6f314 - Show all commits

View file

@ -21,18 +21,18 @@ neo-go wallet export -w <path_to_your_wallet> -d <address_from_p1>
### Container
```java
import info.FrostFS.sdk.enums.BasicAcl;
import info.FrostFS.sdk.dto.container.Container;
import info.FrostFS.sdk.dto.netmap.PlacementPolicy;
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;
public class ContainerExample {
public void example() {
Client client = new Client( < your_key >);
GrpcClient grpcClient = new GrpcClient( < your_host >);
FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client);
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
// Create container
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.ObjectFilter;
import info.FrostFS.sdk.dto.object.ObjectHeader;
import info.FrostFS.sdk.jdo.PutObjectParameters;
import info.FrostFS.sdk.services.FrostFSClient;
import java.io.FileInputStream;
@ -66,9 +67,8 @@ import java.io.IOException;
public class ObjectExample {
public void example() {
Client client = new Client( < your_key >);
GrpcClient grpcClient = new GrpcClient( < your_host >);
FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client);
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
// Put object
info.FrostFS.sdk.dto.object.ObjectId objectId;
@ -76,7 +76,9 @@ public class ObjectExample {
var cat = new ObjectHeader(
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) {
throw new RuntimeException(e);
}

View file

@ -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();
}
}

View file

@ -0,0 +1,5 @@
package info.FrostFS.sdk.constants;
public class CryptoConst {
public static final String SIGNATURE_ALGORITHM = "NONEwithECDSAinP1363Format";
}

View file

@ -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.Version;

View file

@ -1,4 +1,4 @@
package info.FrostFS.sdk.tools;
package info.FrostFS.sdk.jdo;
import io.grpc.ChannelCredentials;
import org.apache.commons.lang3.StringUtils;

View file

@ -1,4 +1,4 @@
package info.FrostFS.sdk.tools;
package info.FrostFS.sdk.jdo;
import java.security.PrivateKey;

View file

@ -1,4 +1,4 @@
package info.FrostFS.sdk.tools;
package info.FrostFS.sdk.jdo;
import java.util.HashMap;
import java.util.Map;

View file

@ -1,4 +1,4 @@
package info.FrostFS.sdk.tools;
package info.FrostFS.sdk.jdo;
import info.FrostFS.sdk.dto.object.ObjectHeader;

View file

@ -1,6 +1,6 @@
package info.FrostFS.sdk.services;
import info.FrostFS.sdk.tools.ClientEnvironment;
import info.FrostFS.sdk.jdo.ClientEnvironment;
public class ContextAccessor {
private final ClientEnvironment context;

View file

@ -1,29 +1,32 @@
package info.FrostFS.sdk.services;
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.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.NodeInfo;
import info.FrostFS.sdk.dto.object.ObjectFilter;
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.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.tools.ClientEnvironment;
import info.FrostFS.sdk.tools.NetworkSettings;
import io.grpc.Channel;
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;
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 NetmapService netmapService;
private final ObjectService objectService;
@ -32,7 +35,7 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
public FrostFSClient(ClientSettings clientSettings) {
if (isNull(clientSettings)) {
throw new IllegalArgumentException("Options must be initialized");
throw new IllegalArgumentException(ERROR_CLIENT_OPTIONS_INIT);
}
clientSettings.validate();
@ -53,9 +56,9 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
private void checkFrostFsVersionSupport(Version version) {
var localNodeInfo = netmapService.getLocalNodeInfo();
if (!localNodeInfo.getVersion().isSupported(version)) {
var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion());
System.out.println(msg);
throw new IllegalArgumentException(msg);
throw new IllegalArgumentException(
String.format(ERROR_VERSION_SUPPORT_TEMPLATE, localNodeInfo.getVersion())
);
}
}

View file

@ -2,7 +2,7 @@ package info.FrostFS.sdk.services;
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
import info.FrostFS.sdk.dto.netmap.NodeInfo;
import info.FrostFS.sdk.tools.NetworkSettings;
import info.FrostFS.sdk.jdo.NetworkSettings;
public interface NetmapClient {
NetmapSnapshot getNetmapSnapshot();

View file

@ -1,11 +1,11 @@
package info.FrostFS.sdk.services;
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.ObjectFrostFS;
import info.FrostFS.sdk.dto.object.ObjectHeader;
import info.FrostFS.sdk.dto.object.ObjectId;
import info.FrostFS.sdk.jdo.PutObjectParameters;
public interface ObjectClient {
ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId);

View file

@ -2,23 +2,23 @@ package info.FrostFS.sdk.services.impl;
import frostFS.container.ContainerServiceGrpc;
import frostFS.container.Service;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.dto.container.Container;
import info.FrostFS.sdk.dto.container.ContainerId;
import info.FrostFS.sdk.mappers.container.ContainerIdMapper;
import info.FrostFS.sdk.mappers.container.ContainerMapper;
import info.FrostFS.sdk.jdo.ClientEnvironment;
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.ContainerMapper;
import info.FrostFS.sdk.services.ContainerClient;
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.stream.Collectors;
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestSigner.sign;
import static info.FrostFS.sdk.RequestSigner.signRFC6979;
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.tools.RequestSigner.sign;
import static info.FrostFS.sdk.tools.RequestSigner.signRFC6979;
public class ContainerService extends ContextAccessor implements ContainerClient {
private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;

View file

@ -3,20 +3,20 @@ package info.FrostFS.sdk.services.impl;
import frostFS.netmap.NetmapServiceGrpc;
import frostFS.netmap.Service;
import frostFS.netmap.Types;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.dto.netmap.NetmapSnapshot;
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.NodeInfoMapper;
import info.FrostFS.sdk.services.ContextAccessor;
import info.FrostFS.sdk.services.NetmapClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import info.FrostFS.sdk.tools.NetworkSettings;
import info.FrostFS.sdk.tools.Verifier;
import java.nio.charset.StandardCharsets;
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestSigner.sign;
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.tools.RequestSigner.sign;
import static java.util.Objects.nonNull;
public class NetmapService extends ContextAccessor implements NetmapClient {

View file

@ -2,11 +2,14 @@ package info.FrostFS.sdk.services.impl;
import frostFS.object.Service;
import frostFS.object.Types;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.tools.Verifier;
import java.util.Iterator;
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 ObjectReader(Iterator<Service.GetResponse> call) {
@ -15,14 +18,14 @@ public class ObjectReader {
public Types.Object readHeader() {
if (!call.hasNext()) {
throw new IllegalArgumentException("unexpected end of stream");
throw new IllegalArgumentException(ERROR_UNEXPECTED_STREAM);
}
var response = call.next();
Verifier.checkResponse(response);
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()
@ -40,7 +43,7 @@ public class ObjectReader {
Verifier.checkResponse(response);
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();

View file

@ -5,21 +5,22 @@ import com.google.protobuf.ByteString;
import frostFS.object.ObjectServiceGrpc;
import frostFS.object.Service;
import frostFS.refs.Types;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.constants.AppConst;
import info.FrostFS.sdk.dto.container.ContainerId;
import info.FrostFS.sdk.dto.Split;
import info.FrostFS.sdk.dto.container.ContainerId;
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.object.ObjectFilterMapper;
import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper;
import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper;
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.ObjectClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import info.FrostFS.sdk.tools.PutObjectParameters;
import info.FrostFS.sdk.tools.Verifier;
import org.apache.commons.collections4.CollectionUtils;
import java.io.FileInputStream;
@ -29,12 +30,14 @@ import java.util.Arrays;
import java.util.List;
import static info.FrostFS.sdk.Helper.getSha256;
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestConstructor.addObjectSessionToken;
import static info.FrostFS.sdk.RequestSigner.sign;
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.tools.RequestConstructor.addObjectSessionToken;
import static info.FrostFS.sdk.tools.RequestSigner.sign;
import static java.util.Objects.nonNull;
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.ObjectServiceStub objectServiceClient;
private final ObjectTools objectTools;
@ -257,7 +260,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient {
var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize());
var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength();
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];

View file

@ -5,17 +5,17 @@ import frostFS.object.Types;
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.mappers.object.ObjectHeaderMapper;
import info.FrostFS.sdk.mappers.object.ObjectIdMapper;
import info.FrostFS.sdk.jdo.ClientEnvironment;
import info.FrostFS.sdk.mappers.OwnerIdMapper;
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.ToolsClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import org.apache.commons.collections4.ListUtils;
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;
public class ObjectTools extends ContextAccessor implements ToolsClient {

View file

@ -1,7 +1,7 @@
package info.FrostFS.sdk.services.impl;
import frostFS.object.Service;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.tools.Verifier;
import java.util.Iterator;
import java.util.List;

View file

@ -4,14 +4,14 @@ import frostFS.session.Service;
import frostFS.session.SessionServiceGrpc;
import frostFS.session.Types;
import info.FrostFS.sdk.dto.SessionToken;
import info.FrostFS.sdk.jdo.ClientEnvironment;
import info.FrostFS.sdk.mappers.OwnerIdMapper;
import info.FrostFS.sdk.mappers.SessionMapper;
import info.FrostFS.sdk.services.ContextAccessor;
import info.FrostFS.sdk.services.SessionClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestSigner.sign;
import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.tools.RequestSigner.sign;
public class SessionService extends ContextAccessor implements SessionClient {
private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub;

View file

@ -1,4 +1,4 @@
package info.FrostFS.sdk;
package info.FrostFS.sdk.tools;
import io.grpc.Channel;
import io.grpc.ChannelCredentials;
@ -10,6 +10,7 @@ import java.net.URISyntaxException;
import static java.util.Objects.isNull;
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) {
try {
@ -19,8 +20,7 @@ public class GrpcClient {
return channelBuilder.usePlaintext().build();
} catch (URISyntaxException exp) {
var message = String.format("Host %s has invalid format. Error: %s", host, exp.getMessage());
throw new IllegalArgumentException(message);
throw new IllegalArgumentException(String.format(ERROR_INVALID_HOST_TEMPLATE, host, exp.getMessage()));
}
}
}

View file

@ -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);
}
}

View file

@ -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 info.FrostFS.sdk.dto.MetaHeader;
import info.FrostFS.sdk.jdo.ECDsa;
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;
public class RequestConstructor {
public static void addMetaHeader(AbstractMessage.Builder request) {
public static void addMetaHeader(Message.Builder request) {
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) {
metaHeader = MetaHeaderMapper.toGrpcMessage(MetaHeader.getDefault());
var field = request.getDescriptorForType().findFieldByName("meta_header");
request.setField(field, metaHeader);
setField(request, META_HEADER_FIELD_NAME, metaHeader);
}
}
public static void addObjectSessionToken(AbstractMessage.Builder request,
public static void addObjectSessionToken(Message.Builder request,
Types.SessionToken sessionToken,
frostFS.refs.Types.ContainerID cid,
frostFS.refs.Types.ObjectID oid,
Types.ObjectSessionContext.Verb verb,
ECDsa key) {
var headerField = request.getDescriptorForType().findFieldByName("meta_header");
var header = (Types.RequestMetaHeader) request.getField(headerField);
var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME);
if (header.getSessionToken().getSerializedSize() > 0) {
return;
}
@ -46,6 +47,6 @@ public class RequestConstructor {
.setBody(body)
.build();
request.setField(headerField, header.toBuilder().setSessionToken(sessionToken).build());
setField(request, META_HEADER_FIELD_NAME, header.toBuilder().setSessionToken(sessionToken).build());
}
}

View file

@ -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.Message;
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.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
@ -15,17 +15,22 @@ import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import java.math.BigInteger;
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.util.BigIntegers.asUnsignedByteArray;
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 byte[] signData(ECDsa key, byte[] data) {
var hash = new byte[65];
hash[0] = 0x04;
try {
Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format");
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(key.getPrivateKey());
signature.update(DigestUtils.sha512(data));
byte[] sig = signature.sign();
@ -62,7 +67,7 @@ public class RequestSigner {
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()
.setKey(ByteString.copyFrom(key.getPublicKeyByte()))
.setSign(ByteString.copyFrom(signRFC6979(key, message.toByteArray())))
@ -76,7 +81,7 @@ public class RequestSigner {
.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();
return frostFS.refs.Types.Signature.newBuilder()
.setKey(ByteString.copyFrom(key.getPublicKeyByte()))
@ -84,39 +89,32 @@ public class RequestSigner {
.build();
}
public static void sign(AbstractMessage.Builder request, ECDsa key) {
var meta = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("meta_header"));
var body = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("body"));
var verify = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("verify_header"));
public static void sign(Message.Builder request, ECDsa key) {
var meta = getField(request, META_HEADER_FIELD_NAME);
var body = getField(request, BODY_FIELD_NAME);
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) {
verifyBuilder = Types.RequestVerificationHeader.newBuilder();
} else if (verify instanceof Types.ResponseVerificationHeader) {
verifyBuilder = Types.ResponseVerificationHeader.newBuilder();
} else {
throw new IllegalArgumentException("Unsopported message type");
}
var verifyOrigin = (AbstractMessage) verify.getField(verify.getDescriptorForType().findFieldByName("origin"));
if (verifyOrigin.getSerializedSize() == 0) {
verifyBuilder.setField(
verifyBuilder.getDescriptorForType().findFieldByName("body_signature"),
signMessagePart(key, body)
throw new IllegalArgumentException(
String.format(ERROR_UNSUPPORTED_TYPE_TEMPLATE, verify.getClass().getName())
);
} else {
verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin);
}
verifyBuilder.setField(
verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"),
signMessagePart(key, meta)
);
verifyBuilder.setField(
verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"),
signMessagePart(key, verifyOrigin)
);
if (verifyOrigin.getSerializedSize() == 0) {
setField(verifyBuilder, BODY_SIGNATURE_FIELD_NAME, signMessagePart(key, body));
} else {
setField(verifyBuilder, ORIGIN_FIELD_NAME, verifyOrigin);
}
request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build());
setField(verifyBuilder, META_SIGNATURE_FIELD_NAME, signMessagePart(key, meta));
setField(verifyBuilder, ORIGIN_SIGNATURE_FIELD_NAME, signMessagePart(key, verifyOrigin));
setField(request, VERIFY_HEADER_FIELD_NAME, verifyBuilder.build());
}
}

View file

@ -1,7 +1,7 @@
package info.FrostFS.sdk;
package info.FrostFS.sdk.tools;
import com.google.protobuf.AbstractMessage;
import frostFS.refs.Types;
import com.google.protobuf.Message;
import frostFS.session.Types;
import info.FrostFS.sdk.mappers.StatusMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.asn1.sec.SECNamedCurves;
@ -17,17 +17,20 @@ import java.security.Signature;
import java.util.Arrays;
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 org.bouncycastle.crypto.util.DigestFactory.createSHA256;
import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray;
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 boolean verifyRFC6979(Types.SignatureRFC6979 signature, AbstractMessage message) {
return verifyRFC6979(
signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray()
);
public static boolean verifyRFC6979(frostFS.refs.Types.SignatureRFC6979 signature, Message data) {
return verifyRFC6979(signature.getKey().toByteArray(), data.toByteArray(), signature.getSign().toByteArray());
}
public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) {
@ -49,8 +52,7 @@ public class Verifier {
private static BigInteger[] decodeSignature(byte[] sig) {
if (sig.length != RFC6979_SIG_SIZE) {
throw new IllegalArgumentException(
String.format("Wrong signature size. Expected length=%s, actual=%s",
RFC6979_SIG_SIZE, sig.length)
String.format(ERROR_WRONG_SIG_SIZE_TEMPLATE, RFC6979_SIG_SIZE, sig.length)
);
}
@ -61,42 +63,40 @@ public class Verifier {
return rs;
}
public static void checkResponse(AbstractMessage response) {
public static void checkResponse(Message 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());
if (!status.isSuccess()) {
throw new IllegalArgumentException(status.toString());
}
}
public static boolean verify(AbstractMessage message) {
var body = (AbstractMessage) message.getField(message.getDescriptorForType().findFieldByName("body"));
var metaHeader = (frostFS.session.Types.ResponseMetaHeader)
message.getField(message.getDescriptorForType().findFieldByName("meta_header"));
var verifyHeader = (frostFS.session.Types.ResponseVerificationHeader)
message.getField(message.getDescriptorForType().findFieldByName("verify_header"));
public static boolean verify(Message response) {
var body = getField(response, BODY_FIELD_NAME);
var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME);
var verifyHeader = (Types.ResponseVerificationHeader) getField(response, VERIFY_HEADER_FIELD_NAME);
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.ResponseVerificationHeader verification) {
if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false;
var origin = verification.getOrigin();
if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false;
if (origin.getSerializedSize() == 0) {
return verifyMessagePart(verification.getBodySignature(), body);
return verifyMessagePart(verification.getBodySignature(), data);
}
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;
var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray());
@ -107,7 +107,7 @@ public class Verifier {
public static boolean verifyData(PublicKey publicKey, byte[] data, byte[] sig) {
try {
Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format");
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(DigestUtils.sha512(data));
return signature.verify(Arrays.copyOfRange(sig, 1, sig.length));

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project 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">
<modelVersion>4.0.0</modelVersion>
<parent>

View file

@ -1,7 +1,7 @@
package info.FrostFS.sdk;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
import com.google.protobuf.Message;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import java.math.BigInteger;
@ -30,7 +30,7 @@ public class Helper {
return getSha256Instance().digest(value);
}
public static ByteString getSha256(AbstractMessage value) {
public static ByteString getSha256(Message value) {
return ByteString.copyFrom(getSha256(value.toByteArray()));
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project 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">
<modelVersion>4.0.0</modelVersion>
<parent>

View file

@ -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";
}