Initial
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
DerivedData/
|
||||
.DS_Store
|
||||
xcuserdata/
|
||||
497
NearDrop.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,497 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 56;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
698DFAE629E2F91A0064F247 /* NearbyConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 698DFAE529E2F91A0064F247 /* NearbyConnection.swift */; };
|
||||
698DFB0329E362140064F247 /* NDNotificationCenterHackery.m in Sources */ = {isa = PBXBuildFile; fileRef = 698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */; };
|
||||
69D2C32D29E77F2200EC7E30 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C32B29E77F2200EC7E30 /* Localizable.strings */; };
|
||||
69D2C32F29E7898C00EC7E30 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C32E29E7898C00EC7E30 /* MainMenu.xib */; };
|
||||
69D2C33829E78DF400EC7E30 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */; };
|
||||
69DA9A1229E0BF5100A442DA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A1129E0BF5100A442DA /* AppDelegate.swift */; };
|
||||
69DA9A1429E0BF5200A442DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69DA9A1329E0BF5200A442DA /* Assets.xcassets */; };
|
||||
69DA9A1F29E0C0B300A442DA /* NearbyConnectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A1E29E0C0B300A442DA /* NearbyConnectionManager.swift */; };
|
||||
69DA9A2129E0CC4E00A442DA /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2029E0CC4E00A442DA /* Data+Extensions.swift */; };
|
||||
69DA9A2329E17F0400A442DA /* InboundNearbyConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2229E17F0400A442DA /* InboundNearbyConnection.swift */; };
|
||||
69DA9A2629E189EF00A442DA /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = 69DA9A2529E189EF00A442DA /* SwiftProtobuf */; };
|
||||
69DA9A2E29E18CB500A442DA /* ukey.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2829E18CB500A442DA /* ukey.pb.swift */; };
|
||||
69DA9A2F29E18CB500A442DA /* wire_format.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2929E18CB500A442DA /* wire_format.pb.swift */; };
|
||||
69DA9A3029E18CB500A442DA /* device_to_device_messages.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2A29E18CB500A442DA /* device_to_device_messages.pb.swift */; };
|
||||
69DA9A3129E18CB500A442DA /* offline_wire_formats.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2B29E18CB500A442DA /* offline_wire_formats.pb.swift */; };
|
||||
69DA9A3229E18CB500A442DA /* securegcm.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2C29E18CB500A442DA /* securegcm.pb.swift */; };
|
||||
69DA9A3329E18CB500A442DA /* securemessage.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2D29E18CB500A442DA /* securemessage.pb.swift */; };
|
||||
69DA9A3629E1994C00A442DA /* SwiftECC in Frameworks */ = {isa = PBXBuildFile; productRef = 69DA9A3529E1994C00A442DA /* SwiftECC */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
698DFAFF29E353220064F247 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
698DFAE529E2F91A0064F247 /* NearbyConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearbyConnection.swift; sourceTree = "<group>"; };
|
||||
698DFAED29E353220064F247 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
|
||||
698DFAEF29E353220064F247 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
|
||||
698DFB0029E362140064F247 /* NearDrop-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NearDrop-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
698DFB0129E362140064F247 /* NDNotificationCenterHackery.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NDNotificationCenterHackery.h; sourceTree = "<group>"; };
|
||||
698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NDNotificationCenterHackery.m; sourceTree = "<group>"; };
|
||||
69D2C32C29E77F2200EC7E30 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
69D2C32E29E7898C00EC7E30 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
|
||||
69D2C33029E789AF00EC7E30 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
69D2C33729E78DF400EC7E30 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = Base; path = Base.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
69D2C33929E78DFD00EC7E30 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
69DA9A0E29E0BF5100A442DA /* NearDrop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NearDrop.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
69DA9A1129E0BF5100A442DA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
69DA9A1329E0BF5200A442DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
69DA9A1829E0BF5200A442DA /* NearDrop.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NearDrop.entitlements; sourceTree = "<group>"; };
|
||||
69DA9A1E29E0C0B300A442DA /* NearbyConnectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearbyConnectionManager.swift; sourceTree = "<group>"; };
|
||||
69DA9A2029E0CC4E00A442DA /* Data+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Extensions.swift"; sourceTree = "<group>"; };
|
||||
69DA9A2229E17F0400A442DA /* InboundNearbyConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboundNearbyConnection.swift; sourceTree = "<group>"; };
|
||||
69DA9A2829E18CB500A442DA /* ukey.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ukey.pb.swift; sourceTree = "<group>"; };
|
||||
69DA9A2929E18CB500A442DA /* wire_format.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = wire_format.pb.swift; sourceTree = "<group>"; };
|
||||
69DA9A2A29E18CB500A442DA /* device_to_device_messages.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = device_to_device_messages.pb.swift; sourceTree = "<group>"; };
|
||||
69DA9A2B29E18CB500A442DA /* offline_wire_formats.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = offline_wire_formats.pb.swift; sourceTree = "<group>"; };
|
||||
69DA9A2C29E18CB500A442DA /* securegcm.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securegcm.pb.swift; sourceTree = "<group>"; };
|
||||
69DA9A2D29E18CB500A442DA /* securemessage.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securemessage.pb.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
69DA9A0B29E0BF5100A442DA /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
69DA9A3629E1994C00A442DA /* SwiftECC in Frameworks */,
|
||||
69DA9A2629E189EF00A442DA /* SwiftProtobuf in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
698DFAEC29E353220064F247 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
698DFAED29E353220064F247 /* UserNotifications.framework */,
|
||||
698DFAEF29E353220064F247 /* UserNotificationsUI.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
69DA9A0529E0BF5100A442DA = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
69DA9A1029E0BF5100A442DA /* NearDrop */,
|
||||
698DFAEC29E353220064F247 /* Frameworks */,
|
||||
69DA9A0F29E0BF5100A442DA /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
69DA9A0F29E0BF5100A442DA /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
69DA9A0E29E0BF5100A442DA /* NearDrop.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
69DA9A1029E0BF5100A442DA /* NearDrop */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
69DA9A2729E18CB500A442DA /* Protobuf */,
|
||||
69DA9A1129E0BF5100A442DA /* AppDelegate.swift */,
|
||||
69DA9A1329E0BF5200A442DA /* Assets.xcassets */,
|
||||
69DA9A1E29E0C0B300A442DA /* NearbyConnectionManager.swift */,
|
||||
69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */,
|
||||
69D2C32B29E77F2200EC7E30 /* Localizable.strings */,
|
||||
69DA9A2229E17F0400A442DA /* InboundNearbyConnection.swift */,
|
||||
698DFB0129E362140064F247 /* NDNotificationCenterHackery.h */,
|
||||
698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */,
|
||||
698DFAE529E2F91A0064F247 /* NearbyConnection.swift */,
|
||||
69DA9A2029E0CC4E00A442DA /* Data+Extensions.swift */,
|
||||
69DA9A1829E0BF5200A442DA /* NearDrop.entitlements */,
|
||||
698DFB0029E362140064F247 /* NearDrop-Bridging-Header.h */,
|
||||
69D2C32E29E7898C00EC7E30 /* MainMenu.xib */,
|
||||
);
|
||||
path = NearDrop;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
69DA9A2729E18CB500A442DA /* Protobuf */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
69DA9A2829E18CB500A442DA /* ukey.pb.swift */,
|
||||
69DA9A2929E18CB500A442DA /* wire_format.pb.swift */,
|
||||
69DA9A2A29E18CB500A442DA /* device_to_device_messages.pb.swift */,
|
||||
69DA9A2B29E18CB500A442DA /* offline_wire_formats.pb.swift */,
|
||||
69DA9A2C29E18CB500A442DA /* securegcm.pb.swift */,
|
||||
69DA9A2D29E18CB500A442DA /* securemessage.pb.swift */,
|
||||
);
|
||||
path = Protobuf;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
69DA9A0D29E0BF5100A442DA /* NearDrop */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 69DA9A1B29E0BF5200A442DA /* Build configuration list for PBXNativeTarget "NearDrop" */;
|
||||
buildPhases = (
|
||||
69DA9A0A29E0BF5100A442DA /* Sources */,
|
||||
69DA9A0B29E0BF5100A442DA /* Frameworks */,
|
||||
69DA9A0C29E0BF5100A442DA /* Resources */,
|
||||
698DFAFF29E353220064F247 /* Embed Foundation Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = NearDrop;
|
||||
packageProductDependencies = (
|
||||
69DA9A2529E189EF00A442DA /* SwiftProtobuf */,
|
||||
69DA9A3529E1994C00A442DA /* SwiftECC */,
|
||||
);
|
||||
productName = NearDrop;
|
||||
productReference = 69DA9A0E29E0BF5100A442DA /* NearDrop.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
69DA9A0629E0BF5100A442DA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1430;
|
||||
LastUpgradeCheck = 1430;
|
||||
TargetAttributes = {
|
||||
69DA9A0D29E0BF5100A442DA = {
|
||||
CreatedOnToolsVersion = 14.3;
|
||||
LastSwiftMigration = 1430;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 69DA9A0929E0BF5100A442DA /* Build configuration list for PBXProject "NearDrop" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
ru,
|
||||
);
|
||||
mainGroup = 69DA9A0529E0BF5100A442DA;
|
||||
packageReferences = (
|
||||
69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */,
|
||||
69DA9A3429E1994C00A442DA /* XCRemoteSwiftPackageReference "SwiftECC" */,
|
||||
);
|
||||
productRefGroup = 69DA9A0F29E0BF5100A442DA /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
69DA9A0D29E0BF5100A442DA /* NearDrop */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
69DA9A0C29E0BF5100A442DA /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
69DA9A1429E0BF5200A442DA /* Assets.xcassets in Resources */,
|
||||
69D2C33829E78DF400EC7E30 /* Localizable.stringsdict in Resources */,
|
||||
69D2C32D29E77F2200EC7E30 /* Localizable.strings in Resources */,
|
||||
69D2C32F29E7898C00EC7E30 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
69DA9A0A29E0BF5100A442DA /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
69DA9A2E29E18CB500A442DA /* ukey.pb.swift in Sources */,
|
||||
698DFB0329E362140064F247 /* NDNotificationCenterHackery.m in Sources */,
|
||||
69DA9A2329E17F0400A442DA /* InboundNearbyConnection.swift in Sources */,
|
||||
69DA9A1F29E0C0B300A442DA /* NearbyConnectionManager.swift in Sources */,
|
||||
69DA9A3029E18CB500A442DA /* device_to_device_messages.pb.swift in Sources */,
|
||||
69DA9A3129E18CB500A442DA /* offline_wire_formats.pb.swift in Sources */,
|
||||
69DA9A1229E0BF5100A442DA /* AppDelegate.swift in Sources */,
|
||||
69DA9A2F29E18CB500A442DA /* wire_format.pb.swift in Sources */,
|
||||
69DA9A3329E18CB500A442DA /* securemessage.pb.swift in Sources */,
|
||||
69DA9A2129E0CC4E00A442DA /* Data+Extensions.swift in Sources */,
|
||||
69DA9A3229E18CB500A442DA /* securegcm.pb.swift in Sources */,
|
||||
698DFAE629E2F91A0064F247 /* NearbyConnection.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
69D2C32B29E77F2200EC7E30 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
69D2C32C29E77F2200EC7E30 /* Base */,
|
||||
69D2C33029E789AF00EC7E30 /* ru */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
69D2C33729E78DF400EC7E30 /* Base */,
|
||||
69D2C33929E78DFD00EC7E30 /* ru */,
|
||||
);
|
||||
name = Localizable.stringsdict;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
69DA9A1929E0BF5200A442DA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
69DA9A1A29E0BF5200A442DA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
69DA9A1C29E0BF5200A442DA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
INFOPLIST_KEY_LSUIElement = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainNibFile = MainMenu;
|
||||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
69DA9A1D29E0BF5200A442DA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
INFOPLIST_KEY_LSUIElement = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainNibFile = MainMenu;
|
||||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
69DA9A0929E0BF5100A442DA /* Build configuration list for PBXProject "NearDrop" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
69DA9A1929E0BF5200A442DA /* Debug */,
|
||||
69DA9A1A29E0BF5200A442DA /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
69DA9A1B29E0BF5200A442DA /* Build configuration list for PBXNativeTarget "NearDrop" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
69DA9A1C29E0BF5200A442DA /* Debug */,
|
||||
69DA9A1D29E0BF5200A442DA /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/apple/swift-protobuf.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 1.0.0;
|
||||
};
|
||||
};
|
||||
69DA9A3429E1994C00A442DA /* XCRemoteSwiftPackageReference "SwiftECC" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/leif-ibsen/SwiftECC";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 3.0.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
69DA9A2529E189EF00A442DA /* SwiftProtobuf */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
||||
productName = SwiftProtobuf;
|
||||
};
|
||||
69DA9A3529E1994C00A442DA /* SwiftECC */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 69DA9A3429E1994C00A442DA /* XCRemoteSwiftPackageReference "SwiftECC" */;
|
||||
productName = SwiftECC;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 69DA9A0629E0BF5100A442DA /* Project object */;
|
||||
}
|
||||
7
NearDrop.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "asn1",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/leif-ibsen/ASN1",
|
||||
"state" : {
|
||||
"revision" : "555922e06f1835863d4c0143eb00d0097bcfc707",
|
||||
"version" : "2.0.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "bigint",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/leif-ibsen/BigInt",
|
||||
"state" : {
|
||||
"revision" : "47903c6b2dd2cb3b4484d4524676a2ca8723a871",
|
||||
"version" : "1.9.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-protobuf",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||
"state" : {
|
||||
"revision" : "0af9125c4eae12a4973fb66574c53a54962a9e1e",
|
||||
"version" : "1.21.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftecc",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/leif-ibsen/SwiftECC",
|
||||
"state" : {
|
||||
"revision" : "55493f0609f07b24bf6cd52b90898ed1cefb268e",
|
||||
"version" : "3.5.3"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
}
|
||||
77
NearDrop.xcodeproj/xcshareddata/xcschemes/NearDrop.xcscheme
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "69DA9A0D29E0BF5100A442DA"
|
||||
BuildableName = "NearDrop.app"
|
||||
BlueprintName = "NearDrop"
|
||||
ReferencedContainer = "container:NearDrop.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "69DA9A0D29E0BF5100A442DA"
|
||||
BuildableName = "NearDrop.app"
|
||||
BlueprintName = "NearDrop"
|
||||
ReferencedContainer = "container:NearDrop.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "69DA9A0D29E0BF5100A442DA"
|
||||
BuildableName = "NearDrop.app"
|
||||
BlueprintName = "NearDrop"
|
||||
ReferencedContainer = "container:NearDrop.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
44
NearDrop/AppDelegate.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 08.04.2023.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import UserNotifications
|
||||
|
||||
@main
|
||||
class AppDelegate: NSObject, NSApplicationDelegate{
|
||||
|
||||
private var connectionManager:NearbyConnectionManager?
|
||||
private var statusItem:NSStatusItem?
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
let menu=NSMenu()
|
||||
menu.addItem(withTitle: NSLocalizedString("VisibleToEveryone", value: "Visible to everyone", comment: ""), action: nil, keyEquivalent: "")
|
||||
menu.addItem(withTitle: String(format: NSLocalizedString("DeviceName", value: "Device name: %@", comment: ""), arguments: [Host.current().localizedName!]), action: nil, keyEquivalent: "")
|
||||
menu.addItem(NSMenuItem.separator())
|
||||
menu.addItem(withTitle: NSLocalizedString("Quit", value: "Quit NearDrop", comment: ""), action: #selector(NSApplication.terminate(_:)), keyEquivalent: "")
|
||||
statusItem=NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||
statusItem?.button?.image=NSImage(named: "MenuBarIcon")
|
||||
statusItem?.menu=menu
|
||||
|
||||
let nc=UNUserNotificationCenter.current()
|
||||
nc.requestAuthorization(options: [.alert, .sound]) { granted, err in
|
||||
}
|
||||
let incomingTransfersCategory=NDNotificationCenterHackery.hackedNotificationCategory()
|
||||
let errorsCategory=UNNotificationCategory(identifier: "ERRORS", actions: [], intentIdentifiers: [])
|
||||
nc.setNotificationCategories([incomingTransfersCategory, errorsCategory])
|
||||
connectionManager=NearbyConnectionManager()
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
|
||||
}
|
||||
|
||||
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
11
NearDrop/Assets.xcassets/AccentColor.colorset/Contents.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/1024.png
Normal file
|
After Width: | Height: | Size: 364 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/128.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/16.png
Normal file
|
After Width: | Height: | Size: 1005 B |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/256 1.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/256.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/32 1.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/32.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/512 1.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/512.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
NearDrop/Assets.xcassets/AppIcon.appiconset/64.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
68
NearDrop/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "32 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "64.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "256 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "512 1.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "1024.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
6
NearDrop/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
25
NearDrop/Assets.xcassets/MenuBarIcon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "NearbyShare.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "NearbyShare@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
BIN
NearDrop/Assets.xcassets/MenuBarIcon.imageset/NearbyShare.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
NearDrop/Assets.xcassets/MenuBarIcon.imageset/NearbyShare@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
NearDrop/Base.lproj/Localizable.strings
Normal file
22
NearDrop/Base.lproj/Localizable.stringsdict
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NFiles</key>
|
||||
<dict>
|
||||
<key>NSStringLocalizedFormatKey</key>
|
||||
<string>%#@files@</string>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>NSStringFormatSpecTypeKey</key>
|
||||
<string>NSStringPluralRuleType</string>
|
||||
<key>NSStringFormatValueTypeKey</key>
|
||||
<string>d</string>
|
||||
<key>one</key>
|
||||
<string>%d file</string>
|
||||
<key>other</key>
|
||||
<string>%d files</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
31
NearDrop/Data+Extensions.swift
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Data+URLSafeBase64.swift
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 08.04.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreFoundation
|
||||
|
||||
extension Data{
|
||||
func urlSafeBase64EncodedString() -> String {
|
||||
return String(base64EncodedString().replacingOccurrences(of: "=", with: "").map {
|
||||
if $0=="/"{
|
||||
return "_"
|
||||
} else if $0=="+" {
|
||||
return "-"
|
||||
} else {
|
||||
return $0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static func randomData(length: Int) -> Data{
|
||||
var data=Data(count: length)
|
||||
data.withUnsafeMutableBytes {
|
||||
guard 0 == SecRandomCopyBytes(kSecRandomDefault, length, $0.baseAddress!) else { fatalError() }
|
||||
}
|
||||
return data
|
||||
}
|
||||
}
|
||||
3
NearDrop/GenerateProtobuf.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
ls ProtobufSource | xargs protoc --swift_out=Protobuf --proto_path=ProtobufSource
|
||||
351
NearDrop/InboundNearbyConnection.swift
Normal file
@@ -0,0 +1,351 @@
|
||||
//
|
||||
// InboundNearbyConnection.swift
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 08.04.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
import CryptoKit
|
||||
import CommonCrypto
|
||||
import System
|
||||
|
||||
import SwiftECC
|
||||
import BigInt
|
||||
|
||||
class InboundNearbyConnection: NearbyConnection{
|
||||
|
||||
private var currentState:State = .initial
|
||||
public var delegate:InboundNearbyConnectionDelegate?
|
||||
private var cipherCommitment:Data?
|
||||
|
||||
enum State{
|
||||
case initial, receivedConnectionRequest, sentUkeyServerInit, receivedUkeyClientFinish, sentConnectionResponse, sentPairedKeyResult, receivedPairedKeyResult, waitingForUserConsent, receivingFiles, disconnected
|
||||
}
|
||||
|
||||
override init(connection: NWConnection, id:String) {
|
||||
super.init(connection: connection, id: id)
|
||||
}
|
||||
|
||||
override func handleConnectionClosure() {
|
||||
super.handleConnectionClosure()
|
||||
currentState = .disconnected
|
||||
do{
|
||||
try deletePartiallyReceivedFiles()
|
||||
}catch{
|
||||
print("Error deleting partially received files: \(error)")
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.connectionWasTerminated(connection: self, error: self.lastError)
|
||||
}
|
||||
}
|
||||
|
||||
override internal func processReceivedFrame(frameData:Data){
|
||||
do{
|
||||
switch currentState {
|
||||
case .initial:
|
||||
let frame=try Location_Nearby_Connections_OfflineFrame(serializedData: frameData)
|
||||
try processConnectionRequestFrame(frame)
|
||||
case .receivedConnectionRequest:
|
||||
let msg=try Securegcm_Ukey2Message(serializedData: frameData)
|
||||
ukeyClientInitMsgData=frameData
|
||||
try processUkey2ClientInit(msg)
|
||||
case .sentUkeyServerInit:
|
||||
let msg=try Securegcm_Ukey2Message(serializedData: frameData)
|
||||
try processUkey2ClientFinish(msg, raw: frameData)
|
||||
case .receivedUkeyClientFinish:
|
||||
let frame=try Location_Nearby_Connections_OfflineFrame(serializedData: frameData)
|
||||
try processConnectionResponseFrame(frame)
|
||||
default:
|
||||
let smsg=try Securemessage_SecureMessage(serializedData: frameData)
|
||||
try decryptAndProcessReceivedSecureMessage(smsg)
|
||||
}
|
||||
}catch{
|
||||
lastError=error
|
||||
print("Deserialization error: \(error)")
|
||||
protocolError()
|
||||
}
|
||||
}
|
||||
|
||||
override internal func processTransferSetupFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
if frame.hasV1 && frame.v1.hasType, case .cancel = frame.v1.type {
|
||||
print("Transfer canceled")
|
||||
try sendDisconnectionAndDisconnect()
|
||||
return
|
||||
}
|
||||
switch currentState{
|
||||
case .sentConnectionResponse:
|
||||
try processPairedKeyEncryptionFrame(frame)
|
||||
case .sentPairedKeyResult:
|
||||
try processPairedKeyResultFrame(frame)
|
||||
case .receivedPairedKeyResult:
|
||||
try processIntroductionFrame(frame)
|
||||
default:
|
||||
print("Unexpected connection state in processTransferSetupFrame: \(currentState)")
|
||||
print(frame)
|
||||
}
|
||||
}
|
||||
|
||||
override func isServer() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func processFileChunk(frame: Location_Nearby_Connections_PayloadTransferFrame) throws{
|
||||
let id=frame.payloadHeader.id
|
||||
guard let fileInfo=transferredFiles[id] else { throw NearbyError.protocolError("File payload ID \(id) is not known") }
|
||||
let currentOffset=fileInfo.bytesTransferred
|
||||
guard frame.payloadChunk.offset==currentOffset else { throw NearbyError.protocolError("Invalid offset into file \(frame.payloadChunk.offset), expected \(currentOffset)") }
|
||||
guard currentOffset+Int64(frame.payloadChunk.body.count)<=fileInfo.meta.size else { throw NearbyError.protocolError("Transferred file size exceeds previously specified value") }
|
||||
if frame.payloadChunk.body.count>0{
|
||||
try fileInfo.fileHandle?.write(contentsOf: frame.payloadChunk.body)
|
||||
transferredFiles[id]!.bytesTransferred+=Int64(frame.payloadChunk.body.count)
|
||||
fileInfo.progress?.completedUnitCount=transferredFiles[id]!.bytesTransferred
|
||||
}else if (frame.payloadChunk.flags & 1)==1{
|
||||
try fileInfo.fileHandle?.close()
|
||||
transferredFiles[id]!.fileHandle=nil
|
||||
fileInfo.progress?.unpublish()
|
||||
transferredFiles.removeValue(forKey: id)
|
||||
if transferredFiles.isEmpty{
|
||||
try sendDisconnectionAndDisconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func processConnectionRequestFrame(_ frame:Location_Nearby_Connections_OfflineFrame) throws{
|
||||
guard frame.hasV1 && frame.v1.hasConnectionRequest && frame.v1.connectionRequest.hasEndpointInfo else { throw NearbyError.requiredFieldMissing }
|
||||
guard case .connectionRequest = frame.v1.type else { throw NearbyError.protocolError("Unexpected frame type \(frame.v1.type)") }
|
||||
let endpointInfo=frame.v1.connectionRequest.endpointInfo
|
||||
guard endpointInfo.count>17 else { throw NearbyError.protocolError("Endpoint info too short") }
|
||||
let deviceNameLength=Int(endpointInfo[17])
|
||||
guard endpointInfo.count>=deviceNameLength+18 else { throw NearbyError.protocolError("Endpoint info too short to contain the device name") }
|
||||
guard let deviceName=String(data: endpointInfo[18..<(18+deviceNameLength)], encoding: .utf8) else { throw NearbyError.protocolError("Device name is not valid UTF-8") }
|
||||
let rawDeviceType:Int=Int(endpointInfo[0] & 7) >> 1
|
||||
remoteDeviceInfo=RemoteDeviceInfo(name: deviceName, type: RemoteDeviceInfo.DeviceType.fromRawValue(value: rawDeviceType))
|
||||
currentState = .receivedConnectionRequest
|
||||
}
|
||||
|
||||
private func processUkey2ClientInit(_ msg:Securegcm_Ukey2Message) throws{
|
||||
guard msg.hasMessageType, msg.hasMessageData else { throw NearbyError.requiredFieldMissing }
|
||||
guard case .clientInit = msg.messageType else{
|
||||
sendUkey2Alert(type: .badMessageType)
|
||||
throw NearbyError.ukey2
|
||||
}
|
||||
let clientInit:Securegcm_Ukey2ClientInit
|
||||
do{
|
||||
clientInit=try Securegcm_Ukey2ClientInit(serializedData: msg.messageData)
|
||||
}catch{
|
||||
sendUkey2Alert(type: .badMessageData)
|
||||
throw NearbyError.ukey2
|
||||
}
|
||||
guard clientInit.version==1 else{
|
||||
sendUkey2Alert(type: .badVersion)
|
||||
throw NearbyError.ukey2
|
||||
}
|
||||
guard clientInit.random.count==32 else{
|
||||
sendUkey2Alert(type: .badRandom)
|
||||
throw NearbyError.ukey2
|
||||
}
|
||||
var found=false
|
||||
for commitment in clientInit.cipherCommitments{
|
||||
if case .p256Sha512 = commitment.handshakeCipher{
|
||||
found=true
|
||||
cipherCommitment=commitment.commitment
|
||||
break
|
||||
}
|
||||
}
|
||||
guard found else{
|
||||
sendUkey2Alert(type: .badHandshakeCipher)
|
||||
throw NearbyError.ukey2
|
||||
}
|
||||
guard clientInit.nextProtocol=="AES_256_CBC-HMAC_SHA256" else{
|
||||
sendUkey2Alert(type: .badNextProtocol)
|
||||
throw NearbyError.ukey2
|
||||
}
|
||||
|
||||
let domain=Domain.instance(curve: .EC256r1)
|
||||
let (pubKey, privKey)=domain.makeKeyPair()
|
||||
publicKey=pubKey
|
||||
privateKey=privKey
|
||||
|
||||
var serverInit=Securegcm_Ukey2ServerInit()
|
||||
serverInit.version=1
|
||||
serverInit.random=Data.randomData(length: 32)
|
||||
serverInit.handshakeCipher = .p256Sha512
|
||||
|
||||
var pkey=Securemessage_GenericPublicKey()
|
||||
pkey.type = .ecP256
|
||||
pkey.ecP256PublicKey=Securemessage_EcP256PublicKey()
|
||||
pkey.ecP256PublicKey.x=Data(pubKey.w.x.asSignedBytes())
|
||||
pkey.ecP256PublicKey.y=Data(pubKey.w.y.asSignedBytes())
|
||||
serverInit.publicKey=try pkey.serializedData()
|
||||
|
||||
var serverInitMsg=Securegcm_Ukey2Message()
|
||||
serverInitMsg.messageType = .serverInit
|
||||
serverInitMsg.messageData=try serverInit.serializedData()
|
||||
let serverInitData=try serverInitMsg.serializedData()
|
||||
ukeyServerInitMsgData=serverInitData
|
||||
sendFrameAsync(serverInitData)
|
||||
currentState = .sentUkeyServerInit
|
||||
}
|
||||
|
||||
private func processUkey2ClientFinish(_ msg:Securegcm_Ukey2Message, raw:Data) throws{
|
||||
guard msg.hasMessageType, msg.hasMessageData else { throw NearbyError.requiredFieldMissing }
|
||||
guard case .clientFinish = msg.messageType else { throw NearbyError.ukey2 }
|
||||
|
||||
var sha=SHA512()
|
||||
sha.update(data: raw)
|
||||
guard cipherCommitment==Data(sha.finalize()) else { throw NearbyError.ukey2 }
|
||||
|
||||
let clientFinish=try Securegcm_Ukey2ClientFinished(serializedData: msg.messageData)
|
||||
guard clientFinish.hasPublicKey else {throw NearbyError.requiredFieldMissing }
|
||||
let clientKey=try Securemessage_GenericPublicKey(serializedData: clientFinish.publicKey)
|
||||
|
||||
try finalizeKeyExchange(peerKey: clientKey)
|
||||
|
||||
currentState = .receivedUkeyClientFinish
|
||||
}
|
||||
|
||||
private func processConnectionResponseFrame(_ frame:Location_Nearby_Connections_OfflineFrame) throws{
|
||||
guard frame.hasV1, frame.v1.hasType else { throw NearbyError.requiredFieldMissing }
|
||||
if case .connectionResponse = frame.v1.type {
|
||||
var resp=Location_Nearby_Connections_OfflineFrame()
|
||||
resp.version = .v1
|
||||
resp.v1=Location_Nearby_Connections_V1Frame()
|
||||
resp.v1.type = .connectionResponse
|
||||
resp.v1.connectionResponse=Location_Nearby_Connections_ConnectionResponseFrame()
|
||||
resp.v1.connectionResponse.response = .accept
|
||||
resp.v1.connectionResponse.status=0
|
||||
resp.v1.connectionResponse.osInfo=Location_Nearby_Connections_OsInfo()
|
||||
resp.v1.connectionResponse.osInfo.type = .apple
|
||||
sendFrameAsync(try resp.serializedData())
|
||||
|
||||
encryptionDone=true
|
||||
|
||||
var pairedEncryption=Sharing_Nearby_Frame()
|
||||
pairedEncryption.version = .v1
|
||||
pairedEncryption.v1=Sharing_Nearby_V1Frame()
|
||||
pairedEncryption.v1.type = .pairedKeyEncryption
|
||||
pairedEncryption.v1.pairedKeyEncryption=Sharing_Nearby_PairedKeyEncryptionFrame()
|
||||
// Presumably used for all the phone number stuff that no one needs anyway
|
||||
pairedEncryption.v1.pairedKeyEncryption.secretIDHash=Data.randomData(length: 6)
|
||||
pairedEncryption.v1.pairedKeyEncryption.signedData=Data.randomData(length: 72)
|
||||
try sendTransferSetupFrame(pairedEncryption)
|
||||
currentState = .sentConnectionResponse
|
||||
} else {
|
||||
print("Unhandled offline frame plaintext: \(frame)")
|
||||
}
|
||||
}
|
||||
|
||||
private func processPairedKeyEncryptionFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
guard frame.hasV1, frame.v1.hasPairedKeyEncryption else { throw NearbyError.requiredFieldMissing }
|
||||
var pairedResult=Sharing_Nearby_Frame()
|
||||
pairedResult.version = .v1
|
||||
pairedResult.v1=Sharing_Nearby_V1Frame()
|
||||
pairedResult.v1.type = .pairedKeyResult
|
||||
pairedResult.v1.pairedKeyResult=Sharing_Nearby_PairedKeyResultFrame()
|
||||
pairedResult.v1.pairedKeyResult.status = .unable
|
||||
try sendTransferSetupFrame(pairedResult)
|
||||
currentState = .sentPairedKeyResult
|
||||
}
|
||||
|
||||
private func processPairedKeyResultFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
guard frame.hasV1, frame.v1.hasPairedKeyResult else { throw NearbyError.requiredFieldMissing }
|
||||
currentState = .receivedPairedKeyResult
|
||||
}
|
||||
|
||||
private func processIntroductionFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
guard frame.hasV1, frame.v1.hasIntroduction else { throw NearbyError.requiredFieldMissing }
|
||||
currentState = .waitingForUserConsent
|
||||
let downloadsDirectory=(try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true)).resolvingSymlinksInPath()
|
||||
for file in frame.v1.introduction.fileMetadata{
|
||||
var dest=downloadsDirectory.appendingPathComponent(file.name)
|
||||
if FileManager.default.fileExists(atPath: dest.path){
|
||||
var counter=1
|
||||
var path:String
|
||||
let ext=dest.pathExtension
|
||||
let baseUrl=dest.deletingPathExtension()
|
||||
repeat{
|
||||
path="\(baseUrl.path) (\(counter))"
|
||||
if !ext.isEmpty{
|
||||
path+=".\(ext)"
|
||||
}
|
||||
counter+=1
|
||||
}while FileManager.default.fileExists(atPath: path)
|
||||
dest=URL(fileURLWithPath: path)
|
||||
}
|
||||
let info=InternalFileInfo(meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
|
||||
payloadID: file.payloadID,
|
||||
destinationURL: dest)
|
||||
transferredFiles[file.payloadID]=info
|
||||
}
|
||||
let metadata=TransferMetadata(files: transferredFiles.map({$0.value.meta}))
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.obtainUserConsent(for: metadata, from: self.remoteDeviceInfo!, connection: self)
|
||||
}
|
||||
}
|
||||
|
||||
func submitUserConsent(accepted:Bool){
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
if accepted{
|
||||
self.acceptTransfer()
|
||||
}else{
|
||||
self.rejectTransfer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func acceptTransfer(){
|
||||
do{
|
||||
for (id, file) in transferredFiles{
|
||||
FileManager.default.createFile(atPath: file.destinationURL.path, contents: nil)
|
||||
let handle=try FileHandle(forWritingTo: file.destinationURL)
|
||||
transferredFiles[id]!.fileHandle=handle
|
||||
let progress=Progress()
|
||||
progress.fileURL=file.destinationURL
|
||||
progress.totalUnitCount=file.meta.size
|
||||
progress.kind = .file
|
||||
progress.isPausable=false
|
||||
progress.publish()
|
||||
transferredFiles[id]!.progress=progress
|
||||
transferredFiles[id]!.created=true
|
||||
}
|
||||
|
||||
var frame=Sharing_Nearby_Frame()
|
||||
frame.version = .v1
|
||||
frame.v1.type = .response
|
||||
frame.v1.connectionResponse.status = .accept
|
||||
currentState = .receivingFiles
|
||||
try sendTransferSetupFrame(frame)
|
||||
}catch{
|
||||
print("Error \(error)")
|
||||
protocolError()
|
||||
}
|
||||
}
|
||||
|
||||
private func rejectTransfer(){
|
||||
var frame=Sharing_Nearby_Frame()
|
||||
frame.version = .v1
|
||||
frame.v1.type = .response
|
||||
frame.v1.connectionResponse.status = .reject
|
||||
do{
|
||||
try sendTransferSetupFrame(frame)
|
||||
try sendDisconnectionAndDisconnect()
|
||||
}catch{
|
||||
print("Error \(error)")
|
||||
protocolError()
|
||||
}
|
||||
}
|
||||
|
||||
private func deletePartiallyReceivedFiles() throws{
|
||||
for (_, file) in transferredFiles{
|
||||
guard file.created else { continue }
|
||||
try FileManager.default.removeItem(at: file.destinationURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol InboundNearbyConnectionDelegate{
|
||||
func obtainUserConsent(for transfer:TransferMetadata, from device:RemoteDeviceInfo, connection:InboundNearbyConnection)
|
||||
func connectionWasTerminated(connection:InboundNearbyConnection, error:Error?)
|
||||
}
|
||||
18
NearDrop/MainMenu.xib
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="NearDrop" customModuleProvider="target"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
</objects>
|
||||
</document>
|
||||
20
NearDrop/NDNotificationCenterHackery.h
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// NDNotificationCenterHackery.h
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 10.04.2023.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NDNotificationCenterHackery : NSObject
|
||||
|
||||
+ (UNNotificationCategory*)hackedNotificationCategory;
|
||||
+ (void)removeDefaultAction:(UNMutableNotificationContent*) content;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
49
NearDrop/NDNotificationCenterHackery.m
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// NDNotificationCenterHackery.m
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 10.04.2023.
|
||||
//
|
||||
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#import "NDNotificationCenterHackery.h"
|
||||
|
||||
@interface UNMutableNotificationCategory : UNNotificationCategory
|
||||
@property(copy) NSString *actionsMenuTitle;
|
||||
@property(copy) UNNotificationAction *alternateAction;
|
||||
@property(copy) NSArray *minimalActions;
|
||||
@property unsigned long long backgroundStyle;
|
||||
@property(copy) NSArray *actions;
|
||||
@end
|
||||
|
||||
@interface UNNotificationIcon : NSObject
|
||||
+ (id)iconForApplicationIdentifier:(id)arg1;
|
||||
+ (id)iconAtPath:(id)arg1;
|
||||
+ (id)iconNamed:(id)arg1;
|
||||
@end
|
||||
|
||||
@interface UNMutableNotificationContent (NDPrivateAPIs)
|
||||
@property BOOL hasDefaultAction;
|
||||
@property(copy) NSString *defaultActionTitle;
|
||||
@property(copy) NSString *header;
|
||||
@property (assign,nonatomic) BOOL shouldDisplayActionsInline;
|
||||
@property (assign,nonatomic) BOOL shouldShowSubordinateIcon;
|
||||
@property (nonatomic,copy) NSString * accessoryImageName;
|
||||
@property(copy) UNNotificationIcon *icon;
|
||||
@end
|
||||
|
||||
@implementation NDNotificationCenterHackery
|
||||
|
||||
+ (UNNotificationCategory*)hackedNotificationCategory{
|
||||
UNNotificationAction *accept=[UNNotificationAction actionWithIdentifier:@"ACCEPT" title:NSLocalizedString(@"Accept", nil) options:0];
|
||||
UNNotificationAction *decline=[UNNotificationAction actionWithIdentifier:@"DECLINE" title:NSLocalizedString(@"Decline", nil) options:0];
|
||||
UNMutableNotificationCategory *category=[UNMutableNotificationCategory categoryWithIdentifier:@"INCOMING_TRANSFERS" actions:@[accept, decline] intentIdentifiers:@[] hiddenPreviewsBodyPlaceholder:@"" options: UNNotificationCategoryOptionCustomDismissAction];
|
||||
return category;
|
||||
}
|
||||
|
||||
+ (void)removeDefaultAction:(UNMutableNotificationContent*) content{
|
||||
content.hasDefaultAction=false;
|
||||
}
|
||||
|
||||
@end
|
||||
5
NearDrop/NearDrop-Bridging-Header.h
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import "NDNotificationCenterHackery.h"
|
||||
16
NearDrop/NearDrop.entitlements
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
458
NearDrop/NearbyConnection.swift
Normal file
@@ -0,0 +1,458 @@
|
||||
//
|
||||
// NearbyConnection.swift
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 09.04.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
import CommonCrypto
|
||||
import CryptoKit
|
||||
import System
|
||||
|
||||
import SwiftECC
|
||||
import BigInt
|
||||
|
||||
class NearbyConnection{
|
||||
internal static let SANE_FRAME_LENGTH=5*1024*1024
|
||||
|
||||
internal let connection:NWConnection
|
||||
internal var remoteDeviceInfo:RemoteDeviceInfo?
|
||||
private var payloadBuffers:[Int64:NSMutableData]=[:]
|
||||
internal var encryptionDone:Bool=false
|
||||
internal var transferredFiles:[Int64:InternalFileInfo]=[:]
|
||||
public let id:String
|
||||
internal var lastError:Error?
|
||||
private var connectionClosed:Bool=false
|
||||
|
||||
// UKEY2-related state
|
||||
internal var publicKey:ECPublicKey?
|
||||
internal var privateKey:ECPrivateKey?
|
||||
internal var ukeyClientInitMsgData:Data?
|
||||
internal var ukeyServerInitMsgData:Data?
|
||||
|
||||
// SecureMessage encryption keys
|
||||
internal var decryptKey:[UInt8]?
|
||||
internal var encryptKey:[UInt8]?
|
||||
internal var recvHmacKey:SymmetricKey?
|
||||
internal var sendHmacKey:SymmetricKey?
|
||||
|
||||
// SecureMessage sequence numbers
|
||||
private var serverSeq:Int32=0
|
||||
private var clientSeq:Int32=0
|
||||
|
||||
private(set) var pinCode:String?
|
||||
|
||||
init(connection:NWConnection, id:String) {
|
||||
self.connection=connection
|
||||
self.id=id
|
||||
}
|
||||
|
||||
func start(){
|
||||
connection.stateUpdateHandler={state in
|
||||
if case .ready = state {
|
||||
self.receiveFrameAsync()
|
||||
} else if case .failed(let err) = state {
|
||||
self.lastError=err
|
||||
print("Error opening socket: \(err)")
|
||||
self.handleConnectionClosure()
|
||||
}
|
||||
}
|
||||
connection.start(queue: .global(qos: .utility))
|
||||
}
|
||||
|
||||
internal func handleConnectionClosure(){
|
||||
print("Connection closed")
|
||||
}
|
||||
|
||||
internal func protocolError(){
|
||||
disconnect()
|
||||
}
|
||||
|
||||
internal func processReceivedFrame(frameData:Data){
|
||||
fatalError()
|
||||
}
|
||||
|
||||
internal func processTransferSetupFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
fatalError()
|
||||
}
|
||||
|
||||
internal func isServer() -> Bool{
|
||||
fatalError()
|
||||
}
|
||||
|
||||
internal func processFileChunk(frame:Location_Nearby_Connections_PayloadTransferFrame) throws{
|
||||
protocolError()
|
||||
}
|
||||
|
||||
private func receiveFrameAsync(){
|
||||
connection.receive(minimumIncompleteLength: 4, maximumLength: 4) { content, contentContext, isComplete, error in
|
||||
if self.connectionClosed{
|
||||
return
|
||||
}
|
||||
if isComplete{
|
||||
self.handleConnectionClosure()
|
||||
return
|
||||
}
|
||||
if !(error==nil){
|
||||
self.lastError=error
|
||||
self.protocolError()
|
||||
return
|
||||
}
|
||||
guard let content=content else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
let frameLength:UInt32=UInt32(content[0]) << 24 | UInt32(content[1]) << 16 | UInt32(content[2]) << 8 | UInt32(content[3])
|
||||
guard frameLength<NearbyConnection.SANE_FRAME_LENGTH else {
|
||||
self.lastError=NearbyError.protocolError("Unexpected packet length")
|
||||
self.protocolError()
|
||||
return
|
||||
}
|
||||
self.receiveFrameAsync(length: frameLength)
|
||||
}
|
||||
}
|
||||
|
||||
private func receiveFrameAsync(length:UInt32){
|
||||
connection.receive(minimumIncompleteLength: Int(length), maximumLength: Int(length)) { content, contentContext, isComplete, error in
|
||||
if self.connectionClosed{
|
||||
return
|
||||
}
|
||||
if isComplete{
|
||||
self.handleConnectionClosure()
|
||||
return
|
||||
}
|
||||
guard let content=content else {
|
||||
self.protocolError()
|
||||
return
|
||||
}
|
||||
self.processReceivedFrame(frameData: content)
|
||||
self.receiveFrameAsync()
|
||||
}
|
||||
}
|
||||
|
||||
internal func sendFrameAsync(_ frame:Data){
|
||||
var lengthPrefixedData=Data(capacity: frame.count+4)
|
||||
let length:Int=frame.count
|
||||
lengthPrefixedData.append(contentsOf: [
|
||||
UInt8(length >> 24),
|
||||
UInt8(length >> 16),
|
||||
UInt8(length >> 8),
|
||||
UInt8(length)
|
||||
])
|
||||
lengthPrefixedData.append(frame)
|
||||
connection.send(content: lengthPrefixedData, completion: .contentProcessed({ error in
|
||||
|
||||
}))
|
||||
}
|
||||
|
||||
internal func encryptAndSendOfflineFrame(_ frame:Location_Nearby_Connections_OfflineFrame) throws{
|
||||
var d2dMsg=Securegcm_DeviceToDeviceMessage()
|
||||
serverSeq+=1
|
||||
d2dMsg.sequenceNumber=serverSeq
|
||||
d2dMsg.message=try frame.serializedData()
|
||||
|
||||
let serializedMsg=[UInt8](try d2dMsg.serializedData())
|
||||
let iv=Data.randomData(length: 16)
|
||||
var encryptedData=Data(count: serializedMsg.count+16)
|
||||
var encryptedLength:size_t=0
|
||||
encryptedData.withUnsafeMutableBytes({
|
||||
let status=CCCrypt(
|
||||
CCOperation(kCCEncrypt),
|
||||
CCAlgorithm(kCCAlgorithmAES128),
|
||||
CCOptions(kCCOptionPKCS7Padding),
|
||||
encryptKey, kCCKeySizeAES256,
|
||||
[UInt8](iv),
|
||||
serializedMsg, serializedMsg.count,
|
||||
$0.baseAddress, $0.count,
|
||||
&encryptedLength
|
||||
)
|
||||
guard status==kCCSuccess else { fatalError("CCCrypt error: \(status)") }
|
||||
})
|
||||
|
||||
var hb=Securemessage_HeaderAndBody()
|
||||
hb.body=encryptedData.prefix(encryptedLength)
|
||||
hb.header=Securemessage_Header()
|
||||
hb.header.encryptionScheme = .aes256Cbc
|
||||
hb.header.signatureScheme = .hmacSha256
|
||||
hb.header.iv=iv
|
||||
var md=Securegcm_GcmMetadata()
|
||||
md.type = .deviceToDeviceMessage
|
||||
md.version=1
|
||||
hb.header.publicMetadata=try md.serializedData()
|
||||
|
||||
var smsg=Securemessage_SecureMessage()
|
||||
smsg.headerAndBody=try hb.serializedData()
|
||||
smsg.signature=Data(HMAC<SHA256>.authenticationCode(for: smsg.headerAndBody, using: sendHmacKey!))
|
||||
sendFrameAsync(try smsg.serializedData())
|
||||
}
|
||||
|
||||
internal func sendTransferSetupFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
var transfer=Location_Nearby_Connections_PayloadTransferFrame()
|
||||
transfer.packetType = .data
|
||||
transfer.payloadChunk.offset=0
|
||||
transfer.payloadChunk.flags=0
|
||||
transfer.payloadChunk.body=try frame.serializedData()
|
||||
transfer.payloadHeader.id=Int64.random(in: Int64.min...Int64.max)
|
||||
transfer.payloadHeader.type = .bytes
|
||||
transfer.payloadHeader.totalSize=Int64(transfer.payloadChunk.body.count)
|
||||
transfer.payloadHeader.isSensitive=false
|
||||
|
||||
var wrapper=Location_Nearby_Connections_OfflineFrame()
|
||||
wrapper.version = .v1
|
||||
wrapper.v1=Location_Nearby_Connections_V1Frame()
|
||||
wrapper.v1.type = .payloadTransfer
|
||||
wrapper.v1.payloadTransfer=transfer
|
||||
try encryptAndSendOfflineFrame(wrapper)
|
||||
|
||||
transfer.payloadChunk.flags=1 // .lastChunk
|
||||
transfer.payloadChunk.offset=Int64(transfer.payloadChunk.body.count)
|
||||
transfer.payloadChunk.clearBody()
|
||||
wrapper.v1.payloadTransfer=transfer
|
||||
try encryptAndSendOfflineFrame(wrapper)
|
||||
}
|
||||
|
||||
internal func decryptAndProcessReceivedSecureMessage(_ smsg:Securemessage_SecureMessage) throws{
|
||||
guard smsg.hasSignature, smsg.hasHeaderAndBody else { throw NearbyError.requiredFieldMissing }
|
||||
let hmac=Data(HMAC<SHA256>.authenticationCode(for: smsg.headerAndBody, using: recvHmacKey!))
|
||||
guard hmac==smsg.signature else { throw NearbyError.protocolError("hmac!=signature") }
|
||||
let headerAndBody=try Securemessage_HeaderAndBody(serializedData: smsg.headerAndBody)
|
||||
var decryptedData=Data(count: headerAndBody.body.count)
|
||||
|
||||
var decryptedLength:Int=0
|
||||
decryptedData.withUnsafeMutableBytes({
|
||||
let status=CCCrypt(
|
||||
CCOperation(kCCDecrypt),
|
||||
CCAlgorithm(kCCAlgorithmAES128),
|
||||
CCOptions(kCCOptionPKCS7Padding),
|
||||
decryptKey, kCCKeySizeAES256,
|
||||
[UInt8](headerAndBody.header.iv),
|
||||
[UInt8](headerAndBody.body), headerAndBody.body.count,
|
||||
$0.baseAddress, $0.count,
|
||||
&decryptedLength
|
||||
)
|
||||
guard status==kCCSuccess else { fatalError("CCCrypt error: \(status)") }
|
||||
})
|
||||
decryptedData=decryptedData.prefix(decryptedLength)
|
||||
let d2dMsg=try Securegcm_DeviceToDeviceMessage(serializedData: decryptedData)
|
||||
guard d2dMsg.hasMessage, d2dMsg.hasSequenceNumber else { throw NearbyError.requiredFieldMissing }
|
||||
clientSeq+=1
|
||||
guard d2dMsg.sequenceNumber==clientSeq else { throw NearbyError.protocolError("Wrong sequence number. Expected \(clientSeq), got \(d2dMsg.sequenceNumber)") }
|
||||
let offlineFrame=try Location_Nearby_Connections_OfflineFrame(serializedData: d2dMsg.message)
|
||||
guard offlineFrame.hasV1, offlineFrame.v1.hasType else { throw NearbyError.requiredFieldMissing }
|
||||
|
||||
if case .payloadTransfer = offlineFrame.v1.type {
|
||||
guard offlineFrame.v1.hasPayloadTransfer else { throw NearbyError.requiredFieldMissing }
|
||||
let payloadTransfer=offlineFrame.v1.payloadTransfer
|
||||
let header=payloadTransfer.payloadHeader;
|
||||
let chunk=payloadTransfer.payloadChunk;
|
||||
guard header.hasType, header.hasID else { throw NearbyError.requiredFieldMissing }
|
||||
guard payloadTransfer.hasPayloadChunk, chunk.hasOffset, chunk.hasFlags else { throw NearbyError.requiredFieldMissing }
|
||||
if case .bytes = header.type{
|
||||
let payloadID=header.id
|
||||
if header.totalSize>InboundNearbyConnection.SANE_FRAME_LENGTH{
|
||||
payloadBuffers.removeValue(forKey: payloadID)
|
||||
throw NearbyError.protocolError("Payload too large (\(header.totalSize) bytes)")
|
||||
}
|
||||
if payloadBuffers[payloadID]==nil {
|
||||
payloadBuffers[payloadID]=NSMutableData(capacity: Int(header.totalSize))
|
||||
}
|
||||
let buffer=payloadBuffers[payloadID]!
|
||||
guard chunk.offset==buffer.count else {
|
||||
payloadBuffers.removeValue(forKey: payloadID)
|
||||
throw NearbyError.protocolError("Unexpected chunk offset \(chunk.offset), expected \(buffer.count)")
|
||||
}
|
||||
if chunk.hasBody {
|
||||
buffer.append(chunk.body)
|
||||
}
|
||||
if (chunk.flags & 1)==1 {
|
||||
payloadBuffers.removeValue(forKey: payloadID)
|
||||
let innerFrame=try Sharing_Nearby_Frame(serializedData: buffer as Data)
|
||||
try processTransferSetupFrame(innerFrame)
|
||||
}
|
||||
}else if case .file = header.type{
|
||||
try processFileChunk(frame: payloadTransfer)
|
||||
}
|
||||
}else if case .keepAlive = offlineFrame.v1.type{
|
||||
sendKeepAlive(ack: true)
|
||||
}else{
|
||||
print("Unhandled offline frame encrypted: \(offlineFrame)")
|
||||
}
|
||||
}
|
||||
|
||||
internal static func pinCodeFromAuthKey(_ key:SymmetricKey) -> String{
|
||||
var hash:Int=0
|
||||
var multiplier:Int=1
|
||||
let keyBytes:[UInt8]=key.withUnsafeBytes({
|
||||
return [UInt8]($0)
|
||||
})
|
||||
|
||||
for _byte in keyBytes {
|
||||
let byte=Int(Int8(bitPattern: _byte))
|
||||
hash=(hash+byte*multiplier)%9973
|
||||
multiplier=(multiplier*31)%9973
|
||||
}
|
||||
|
||||
return String(format: "%04d", abs(hash))
|
||||
}
|
||||
|
||||
internal func finalizeKeyExchange(peerKey:Securemessage_GenericPublicKey) throws{
|
||||
guard peerKey.hasEcP256PublicKey else { throw NearbyError.requiredFieldMissing }
|
||||
|
||||
let domain=Domain.instance(curve: .EC256r1)
|
||||
var clientX=peerKey.ecP256PublicKey.x
|
||||
var clientY=peerKey.ecP256PublicKey.y
|
||||
if clientX.count>32{
|
||||
clientX=clientX.suffix(32)
|
||||
}
|
||||
if clientY.count>32{
|
||||
clientY=clientY.suffix(32)
|
||||
}
|
||||
let key=try ECPublicKey(domain: domain, w: Point(BInt(magnitude: [UInt8](clientX)), BInt(magnitude: [UInt8](clientY))))
|
||||
|
||||
let dhs=(try privateKey?.domain.multiplyPoint(key.w, privateKey!.s).x.asMagnitudeBytes())!
|
||||
var sha=SHA256()
|
||||
sha.update(data: dhs)
|
||||
let derivedSecretKey=Data(sha.finalize())
|
||||
|
||||
var ukeyInfo=Data()
|
||||
ukeyInfo.append(ukeyClientInitMsgData!)
|
||||
ukeyInfo.append(ukeyServerInitMsgData!)
|
||||
let authString=HKDF<SHA256>.deriveKey(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 auth".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
|
||||
let nextSecret=HKDF<SHA256>.deriveKey(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 next".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
|
||||
|
||||
pinCode=NearbyConnection.pinCodeFromAuthKey(authString)
|
||||
|
||||
let salt:Data=Data([0x82, 0xAA, 0x55, 0xA0, 0xD3, 0x97, 0xF8, 0x83, 0x46, 0xCA, 0x1C,
|
||||
0xEE, 0x8D, 0x39, 0x09, 0xB9, 0x5F, 0x13, 0xFA, 0x7D, 0xEB, 0x1D,
|
||||
0x4A, 0xB3, 0x83, 0x76, 0xB8, 0x25, 0x6D, 0xA8, 0x55, 0x10])
|
||||
|
||||
let d2dClientKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: nextSecret, salt: salt, info: "client".data(using: .utf8)!, outputByteCount: 32)
|
||||
let d2dServerKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: nextSecret, salt: salt, info: "server".data(using: .utf8)!, outputByteCount: 32)
|
||||
|
||||
sha=SHA256()
|
||||
sha.update(data: "SecureMessage".data(using: .utf8)!)
|
||||
let smsgSalt=Data(sha.finalize())
|
||||
|
||||
let clientKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)})
|
||||
let clientHmacKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32)
|
||||
let serverKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)})
|
||||
let serverHmacKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32)
|
||||
|
||||
if isServer(){
|
||||
decryptKey=clientKey
|
||||
recvHmacKey=clientHmacKey
|
||||
encryptKey=serverKey
|
||||
sendHmacKey=serverHmacKey
|
||||
}else{
|
||||
decryptKey=serverKey
|
||||
recvHmacKey=serverHmacKey
|
||||
encryptKey=clientKey
|
||||
sendHmacKey=clientHmacKey
|
||||
}
|
||||
}
|
||||
|
||||
internal func disconnect(){
|
||||
connection.send(content: nil, isComplete: true, completion: .contentProcessed({ error in
|
||||
self.handleConnectionClosure()
|
||||
}))
|
||||
connectionClosed=true
|
||||
}
|
||||
|
||||
internal func sendDisconnectionAndDisconnect() throws{
|
||||
var offlineFrame=Location_Nearby_Connections_OfflineFrame()
|
||||
offlineFrame.version = .v1
|
||||
offlineFrame.v1.type = .disconnection
|
||||
offlineFrame.v1.disconnection=Location_Nearby_Connections_DisconnectionFrame()
|
||||
|
||||
if encryptionDone{
|
||||
try encryptAndSendOfflineFrame(offlineFrame)
|
||||
}else{
|
||||
sendFrameAsync(try offlineFrame.serializedData())
|
||||
}
|
||||
disconnect()
|
||||
}
|
||||
|
||||
internal func sendUkey2Alert(type:Securegcm_Ukey2Alert.AlertType){
|
||||
var alert=Securegcm_Ukey2Alert()
|
||||
alert.type=type
|
||||
var msg=Securegcm_Ukey2Message()
|
||||
msg.messageType = .alert
|
||||
msg.messageData = try! alert.serializedData()
|
||||
sendFrameAsync(try! msg.serializedData())
|
||||
disconnect()
|
||||
}
|
||||
|
||||
internal func sendKeepAlive(ack:Bool){
|
||||
var offlineFrame=Location_Nearby_Connections_OfflineFrame()
|
||||
offlineFrame.version = .v1
|
||||
offlineFrame.v1.type = .keepAlive
|
||||
offlineFrame.v1.keepAlive.ack=ack
|
||||
|
||||
do{
|
||||
if encryptionDone{
|
||||
try encryptAndSendOfflineFrame(offlineFrame)
|
||||
}else{
|
||||
sendFrameAsync(try offlineFrame.serializedData())
|
||||
}
|
||||
}catch{
|
||||
print("Error sending KEEP_ALIVE: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum NearbyError:Error{
|
||||
case protocolError(_ message:String)
|
||||
case requiredFieldMissing
|
||||
case ukey2
|
||||
case inputOutput(cause:Errno)
|
||||
}
|
||||
|
||||
|
||||
struct RemoteDeviceInfo{
|
||||
let name:String
|
||||
let type:DeviceType
|
||||
|
||||
enum DeviceType{
|
||||
case unknown
|
||||
case phone
|
||||
case tablet
|
||||
case computer
|
||||
|
||||
static func fromRawValue(value:Int) -> DeviceType{
|
||||
switch value {
|
||||
case 0:
|
||||
return .unknown
|
||||
case 1:
|
||||
return .phone
|
||||
case 2:
|
||||
return .tablet
|
||||
case 3:
|
||||
return .computer
|
||||
default:
|
||||
return .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TransferMetadata{
|
||||
let files:[FileMetadata]
|
||||
}
|
||||
|
||||
struct FileMetadata{
|
||||
let name:String
|
||||
let size:Int64
|
||||
let mimeType:String
|
||||
}
|
||||
|
||||
struct InternalFileInfo{
|
||||
let meta:FileMetadata
|
||||
let payloadID:Int64
|
||||
let destinationURL:URL
|
||||
var bytesTransferred:Int64=0
|
||||
var fileHandle:FileHandle?
|
||||
var progress:Progress?
|
||||
var created:Bool=false
|
||||
}
|
||||
134
NearDrop/NearbyConnectionManager.swift
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// NearbyConnectionManager.swift
|
||||
// NearDrop
|
||||
//
|
||||
// Created by Grishka on 08.04.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
import UserNotifications
|
||||
|
||||
class NearbyConnectionManager : NSObject, NetServiceDelegate, InboundNearbyConnectionDelegate, UNUserNotificationCenterDelegate{
|
||||
|
||||
private var tcpListener:NWListener;
|
||||
private let endpointID:[UInt8]=generateEndpointID()
|
||||
private var mdnsService:NetService?
|
||||
private var activeConnections:[String:InboundNearbyConnection]=[:]
|
||||
|
||||
override init() {
|
||||
tcpListener=try! NWListener(using: NWParameters(tls: .none))
|
||||
super.init()
|
||||
UNUserNotificationCenter.current().delegate=self
|
||||
startTCPListener()
|
||||
}
|
||||
|
||||
private func startTCPListener(){
|
||||
tcpListener.stateUpdateHandler={(state:NWListener.State) in
|
||||
if case .ready = state {
|
||||
self.initMDNS()
|
||||
}
|
||||
}
|
||||
tcpListener.newConnectionHandler={(connection:NWConnection) in
|
||||
let id=UUID().uuidString
|
||||
let conn=InboundNearbyConnection(connection: connection, id: id)
|
||||
self.activeConnections[id]=conn
|
||||
conn.delegate=self
|
||||
conn.start()
|
||||
}
|
||||
tcpListener.start(queue: .global(qos: .utility))
|
||||
}
|
||||
|
||||
private static func generateEndpointID()->[UInt8]{
|
||||
var id:[UInt8]=[]
|
||||
let alphabet="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".compactMap {UInt8($0.asciiValue!)}
|
||||
for _ in 0...3{
|
||||
id.append(alphabet[Int.random(in: 0..<alphabet.count)])
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
private func initMDNS(){
|
||||
let nameBytes:[UInt8]=[
|
||||
0x23, // PCP
|
||||
endpointID[0], endpointID[1], endpointID[2], endpointID[3],
|
||||
0xFC, 0x9F, 0x5E, // Service ID hash
|
||||
0, 0
|
||||
]
|
||||
let name=Data(nameBytes).urlSafeBase64EncodedString()
|
||||
// 1 byte: Version(3 bits)|Visibility(1 bit)|Device Type(3 bits)|Reserved(1 bits)
|
||||
// Device types: unknown=0, phone=1, tablet=2, laptop=3
|
||||
var endpointInfo:[UInt8]=[3 << 1]
|
||||
// 16 bytes: unknown random bytes
|
||||
for _ in 0...15{
|
||||
endpointInfo.append(UInt8.random(in: 0...255))
|
||||
}
|
||||
// Device name in UTF-8 prefixed with 1-byte length
|
||||
let hostName=Host.current().localizedName!
|
||||
let hostNameChars=hostName.utf8
|
||||
endpointInfo.append(UInt8(hostNameChars.count))
|
||||
for (i, ch) in hostNameChars.enumerated(){
|
||||
guard i<256 else {break}
|
||||
endpointInfo.append(UInt8(ch))
|
||||
}
|
||||
|
||||
let port:Int32=Int32(tcpListener.port!.rawValue)
|
||||
mdnsService=NetService(domain: "", type: "_FC9F5ED42C8A._tcp.", name: name, port: port)
|
||||
mdnsService?.delegate=self
|
||||
mdnsService?.includesPeerToPeer=true
|
||||
mdnsService?.setTXTRecord(NetService.data(fromTXTRecord: [
|
||||
"n": Data(endpointInfo).urlSafeBase64EncodedString().data(using: .utf8)!
|
||||
]))
|
||||
mdnsService?.publish()
|
||||
}
|
||||
|
||||
func obtainUserConsent(for transfer: TransferMetadata, from device: RemoteDeviceInfo, connection: InboundNearbyConnection) {
|
||||
let notificationContent=UNMutableNotificationContent()
|
||||
notificationContent.title="NearDrop"
|
||||
notificationContent.subtitle=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [connection.pinCode!])
|
||||
let fileStr:String
|
||||
if transfer.files.count==1{
|
||||
fileStr=transfer.files[0].name
|
||||
}else{
|
||||
fileStr=String.localizedStringWithFormat(NSLocalizedString("NFiles", value: "%d files", comment: ""), transfer.files.count)
|
||||
}
|
||||
notificationContent.body=String(format: NSLocalizedString("DeviceSendingFiles", value: "%1$@ is sending you %2$@", comment: ""), arguments: [device.name, fileStr])
|
||||
notificationContent.sound = .default
|
||||
notificationContent.categoryIdentifier="INCOMING_TRANSFERS"
|
||||
notificationContent.userInfo=["transferID": connection.id]
|
||||
NDNotificationCenterHackery.removeDefaultAction(notificationContent)
|
||||
let notificationReq=UNNotificationRequest(identifier: "transfer_"+connection.id, content: notificationContent, trigger: nil)
|
||||
UNUserNotificationCenter.current().add(notificationReq)
|
||||
}
|
||||
|
||||
func connectionWasTerminated(connection:InboundNearbyConnection, error:Error?){
|
||||
activeConnections.removeValue(forKey: connection.id)
|
||||
if let error=error{
|
||||
let notificationContent=UNMutableNotificationContent()
|
||||
notificationContent.title=String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [connection.remoteDeviceInfo!.name])
|
||||
if let ne=(error as? NearbyError){
|
||||
switch ne{
|
||||
case .inputOutput(let er):
|
||||
notificationContent.body=er.localizedDescription
|
||||
case .protocolError(_):
|
||||
notificationContent.body=NSLocalizedString("Error.Protocol", value: "Communication error", comment: "")
|
||||
case .requiredFieldMissing:
|
||||
notificationContent.body=NSLocalizedString("Error.Protocol", value: "Communication error", comment: "")
|
||||
case .ukey2:
|
||||
notificationContent.body=NSLocalizedString("Error.Crypto", value: "Encryption error", comment: "")
|
||||
}
|
||||
}else{
|
||||
notificationContent.body=error.localizedDescription
|
||||
}
|
||||
notificationContent.categoryIdentifier="ERRORS"
|
||||
UNUserNotificationCenter.current().add(UNNotificationRequest(identifier: "transferError_"+connection.id, content: notificationContent, trigger: nil))
|
||||
}
|
||||
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["transfer_"+connection.id])
|
||||
}
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
activeConnections[response.notification.request.content.userInfo["transferID"]! as! String]?.submitUserConsent(accepted: response.actionIdentifier=="ACCEPT")
|
||||
completionHandler()
|
||||
}
|
||||
}
|
||||
|
||||
540
NearDrop/Protobuf/device_to_device_messages.pb.swift
Normal file
@@ -0,0 +1,540 @@
|
||||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: device_to_device_messages.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
/// Type of curve
|
||||
enum Securegcm_Curve: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
case ed25519 // = 1
|
||||
|
||||
init() {
|
||||
self = .ed25519
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 1: self = .ed25519
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .ed25519: return 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securegcm_Curve: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
/// Used by protocols between devices
|
||||
struct Securegcm_DeviceToDeviceMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// the payload of the message
|
||||
var message: Data {
|
||||
get {return _message ?? Data()}
|
||||
set {_message = newValue}
|
||||
}
|
||||
/// Returns true if `message` has been explicitly set.
|
||||
var hasMessage: Bool {return self._message != nil}
|
||||
/// Clears the value of `message`. Subsequent reads from it will return its default value.
|
||||
mutating func clearMessage() {self._message = nil}
|
||||
|
||||
/// the sequence number of the message - must be increasing.
|
||||
var sequenceNumber: Int32 {
|
||||
get {return _sequenceNumber ?? 0}
|
||||
set {_sequenceNumber = newValue}
|
||||
}
|
||||
/// Returns true if `sequenceNumber` has been explicitly set.
|
||||
var hasSequenceNumber: Bool {return self._sequenceNumber != nil}
|
||||
/// Clears the value of `sequenceNumber`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSequenceNumber() {self._sequenceNumber = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _message: Data? = nil
|
||||
fileprivate var _sequenceNumber: Int32? = nil
|
||||
}
|
||||
|
||||
/// sent as the first message from initiator to responder
|
||||
/// in an unauthenticated Diffie-Hellman Key Exchange
|
||||
struct Securegcm_InitiatorHello {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// The session public key to send to the responder
|
||||
var publicDhKey: Securemessage_GenericPublicKey {
|
||||
get {return _publicDhKey ?? Securemessage_GenericPublicKey()}
|
||||
set {_publicDhKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicDhKey` has been explicitly set.
|
||||
var hasPublicDhKey: Bool {return self._publicDhKey != nil}
|
||||
/// Clears the value of `publicDhKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicDhKey() {self._publicDhKey = nil}
|
||||
|
||||
/// The protocol version
|
||||
var protocolVersion: Int32 {
|
||||
get {return _protocolVersion ?? 0}
|
||||
set {_protocolVersion = newValue}
|
||||
}
|
||||
/// Returns true if `protocolVersion` has been explicitly set.
|
||||
var hasProtocolVersion: Bool {return self._protocolVersion != nil}
|
||||
/// Clears the value of `protocolVersion`. Subsequent reads from it will return its default value.
|
||||
mutating func clearProtocolVersion() {self._protocolVersion = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _publicDhKey: Securemessage_GenericPublicKey? = nil
|
||||
fileprivate var _protocolVersion: Int32? = nil
|
||||
}
|
||||
|
||||
/// sent inside the header of the first message from the responder to the
|
||||
/// initiator in an unauthenticated Diffie-Hellman Key Exchange
|
||||
struct Securegcm_ResponderHello {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// The session public key to send to the initiator
|
||||
var publicDhKey: Securemessage_GenericPublicKey {
|
||||
get {return _publicDhKey ?? Securemessage_GenericPublicKey()}
|
||||
set {_publicDhKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicDhKey` has been explicitly set.
|
||||
var hasPublicDhKey: Bool {return self._publicDhKey != nil}
|
||||
/// Clears the value of `publicDhKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicDhKey() {self._publicDhKey = nil}
|
||||
|
||||
/// The protocol version
|
||||
var protocolVersion: Int32 {
|
||||
get {return _protocolVersion ?? 0}
|
||||
set {_protocolVersion = newValue}
|
||||
}
|
||||
/// Returns true if `protocolVersion` has been explicitly set.
|
||||
var hasProtocolVersion: Bool {return self._protocolVersion != nil}
|
||||
/// Clears the value of `protocolVersion`. Subsequent reads from it will return its default value.
|
||||
mutating func clearProtocolVersion() {self._protocolVersion = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _publicDhKey: Securemessage_GenericPublicKey? = nil
|
||||
fileprivate var _protocolVersion: Int32? = nil
|
||||
}
|
||||
|
||||
/// A convenience proto for encoding curve points in affine representation
|
||||
struct Securegcm_EcPoint {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var curve: Securegcm_Curve {
|
||||
get {return _curve ?? .ed25519}
|
||||
set {_curve = newValue}
|
||||
}
|
||||
/// Returns true if `curve` has been explicitly set.
|
||||
var hasCurve: Bool {return self._curve != nil}
|
||||
/// Clears the value of `curve`. Subsequent reads from it will return its default value.
|
||||
mutating func clearCurve() {self._curve = nil}
|
||||
|
||||
/// x and y are encoded in big-endian two's complement
|
||||
/// client MUST verify (x,y) is a valid point on the specified curve
|
||||
var x: Data {
|
||||
get {return _x ?? Data()}
|
||||
set {_x = newValue}
|
||||
}
|
||||
/// Returns true if `x` has been explicitly set.
|
||||
var hasX: Bool {return self._x != nil}
|
||||
/// Clears the value of `x`. Subsequent reads from it will return its default value.
|
||||
mutating func clearX() {self._x = nil}
|
||||
|
||||
var y: Data {
|
||||
get {return _y ?? Data()}
|
||||
set {_y = newValue}
|
||||
}
|
||||
/// Returns true if `y` has been explicitly set.
|
||||
var hasY: Bool {return self._y != nil}
|
||||
/// Clears the value of `y`. Subsequent reads from it will return its default value.
|
||||
mutating func clearY() {self._y = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _curve: Securegcm_Curve? = nil
|
||||
fileprivate var _x: Data? = nil
|
||||
fileprivate var _y: Data? = nil
|
||||
}
|
||||
|
||||
struct Securegcm_SpakeHandshakeMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// Each flow in the protocol bumps this counter
|
||||
var flowNumber: Int32 {
|
||||
get {return _flowNumber ?? 0}
|
||||
set {_flowNumber = newValue}
|
||||
}
|
||||
/// Returns true if `flowNumber` has been explicitly set.
|
||||
var hasFlowNumber: Bool {return self._flowNumber != nil}
|
||||
/// Clears the value of `flowNumber`. Subsequent reads from it will return its default value.
|
||||
mutating func clearFlowNumber() {self._flowNumber = nil}
|
||||
|
||||
/// Some (but not all) SPAKE flows send a point on an elliptic curve
|
||||
var ecPoint: Securegcm_EcPoint {
|
||||
get {return _ecPoint ?? Securegcm_EcPoint()}
|
||||
set {_ecPoint = newValue}
|
||||
}
|
||||
/// Returns true if `ecPoint` has been explicitly set.
|
||||
var hasEcPoint: Bool {return self._ecPoint != nil}
|
||||
/// Clears the value of `ecPoint`. Subsequent reads from it will return its default value.
|
||||
mutating func clearEcPoint() {self._ecPoint = nil}
|
||||
|
||||
/// Some (but not all) SPAKE flows send a hash value
|
||||
var hashValue_p: Data {
|
||||
get {return _hashValue_p ?? Data()}
|
||||
set {_hashValue_p = newValue}
|
||||
}
|
||||
/// Returns true if `hashValue_p` has been explicitly set.
|
||||
var hasHashValue_p: Bool {return self._hashValue_p != nil}
|
||||
/// Clears the value of `hashValue_p`. Subsequent reads from it will return its default value.
|
||||
mutating func clearHashValue_p() {self._hashValue_p = nil}
|
||||
|
||||
/// The last flow of a SPAKE protocol can send an optional payload,
|
||||
/// since the key exchange is already complete on the sender's side.
|
||||
var payload: Data {
|
||||
get {return _payload ?? Data()}
|
||||
set {_payload = newValue}
|
||||
}
|
||||
/// Returns true if `payload` has been explicitly set.
|
||||
var hasPayload: Bool {return self._payload != nil}
|
||||
/// Clears the value of `payload`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPayload() {self._payload = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _flowNumber: Int32? = nil
|
||||
fileprivate var _ecPoint: Securegcm_EcPoint? = nil
|
||||
fileprivate var _hashValue_p: Data? = nil
|
||||
fileprivate var _payload: Data? = nil
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
extension Securegcm_Curve: @unchecked Sendable {}
|
||||
extension Securegcm_DeviceToDeviceMessage: @unchecked Sendable {}
|
||||
extension Securegcm_InitiatorHello: @unchecked Sendable {}
|
||||
extension Securegcm_ResponderHello: @unchecked Sendable {}
|
||||
extension Securegcm_EcPoint: @unchecked Sendable {}
|
||||
extension Securegcm_SpakeHandshakeMessage: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "securegcm"
|
||||
|
||||
extension Securegcm_Curve: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "ED_25519"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securegcm_DeviceToDeviceMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".DeviceToDeviceMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "message"),
|
||||
2: .standard(proto: "sequence_number"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._message) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self._sequenceNumber) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._message {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._sequenceNumber {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_DeviceToDeviceMessage, rhs: Securegcm_DeviceToDeviceMessage) -> Bool {
|
||||
if lhs._message != rhs._message {return false}
|
||||
if lhs._sequenceNumber != rhs._sequenceNumber {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_InitiatorHello: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".InitiatorHello"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "public_dh_key"),
|
||||
2: .standard(proto: "protocol_version"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if let v = self._publicDhKey, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularMessageField(value: &self._publicDhKey) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self._protocolVersion) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicDhKey {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._protocolVersion {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_InitiatorHello, rhs: Securegcm_InitiatorHello) -> Bool {
|
||||
if lhs._publicDhKey != rhs._publicDhKey {return false}
|
||||
if lhs._protocolVersion != rhs._protocolVersion {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_ResponderHello: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".ResponderHello"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "public_dh_key"),
|
||||
2: .standard(proto: "protocol_version"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if let v = self._publicDhKey, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularMessageField(value: &self._publicDhKey) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self._protocolVersion) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicDhKey {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._protocolVersion {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_ResponderHello, rhs: Securegcm_ResponderHello) -> Bool {
|
||||
if lhs._publicDhKey != rhs._publicDhKey {return false}
|
||||
if lhs._protocolVersion != rhs._protocolVersion {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_EcPoint: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".EcPoint"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "curve"),
|
||||
2: .same(proto: "x"),
|
||||
3: .same(proto: "y"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._curve == nil {return false}
|
||||
if self._x == nil {return false}
|
||||
if self._y == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self._curve) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._x) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self._y) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._curve {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._x {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._y {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_EcPoint, rhs: Securegcm_EcPoint) -> Bool {
|
||||
if lhs._curve != rhs._curve {return false}
|
||||
if lhs._x != rhs._x {return false}
|
||||
if lhs._y != rhs._y {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_SpakeHandshakeMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".SpakeHandshakeMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "flow_number"),
|
||||
2: .standard(proto: "ec_point"),
|
||||
3: .standard(proto: "hash_value"),
|
||||
4: .same(proto: "payload"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if let v = self._ecPoint, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self._flowNumber) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &self._ecPoint) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self._hashValue_p) }()
|
||||
case 4: try { try decoder.decodeSingularBytesField(value: &self._payload) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._flowNumber {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._ecPoint {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._hashValue_p {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try { if let v = self._payload {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_SpakeHandshakeMessage, rhs: Securegcm_SpakeHandshakeMessage) -> Bool {
|
||||
if lhs._flowNumber != rhs._flowNumber {return false}
|
||||
if lhs._ecPoint != rhs._ecPoint {return false}
|
||||
if lhs._hashValue_p != rhs._hashValue_p {return false}
|
||||
if lhs._payload != rhs._payload {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
3653
NearDrop/Protobuf/offline_wire_formats.pb.swift
Normal file
1522
NearDrop/Protobuf/securegcm.pb.swift
Normal file
951
NearDrop/Protobuf/securemessage.pb.swift
Normal file
@@ -0,0 +1,951 @@
|
||||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: securemessage.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Proto definitions for SecureMessage format
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
/// Supported "signature" schemes (both symmetric key and public key based)
|
||||
enum Securemessage_SigScheme: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
case hmacSha256 // = 1
|
||||
case ecdsaP256Sha256 // = 2
|
||||
|
||||
/// Not recommended -- use ECDSA_P256_SHA256 instead
|
||||
case rsa2048Sha256 // = 3
|
||||
|
||||
init() {
|
||||
self = .hmacSha256
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 1: self = .hmacSha256
|
||||
case 2: self = .ecdsaP256Sha256
|
||||
case 3: self = .rsa2048Sha256
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .hmacSha256: return 1
|
||||
case .ecdsaP256Sha256: return 2
|
||||
case .rsa2048Sha256: return 3
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securemessage_SigScheme: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
/// Supported encryption schemes
|
||||
enum Securemessage_EncScheme: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
|
||||
/// No encryption
|
||||
case none // = 1
|
||||
case aes256Cbc // = 2
|
||||
|
||||
init() {
|
||||
self = .none
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 1: self = .none
|
||||
case 2: self = .aes256Cbc
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .none: return 1
|
||||
case .aes256Cbc: return 2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securemessage_EncScheme: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
/// A list of supported public key types
|
||||
enum Securemessage_PublicKeyType: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
case ecP256 // = 1
|
||||
case rsa2048 // = 2
|
||||
|
||||
/// 2048-bit MODP group 14, from RFC 3526
|
||||
case dh2048Modp // = 3
|
||||
|
||||
init() {
|
||||
self = .ecP256
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 1: self = .ecP256
|
||||
case 2: self = .rsa2048
|
||||
case 3: self = .dh2048Modp
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .ecP256: return 1
|
||||
case .rsa2048: return 2
|
||||
case .dh2048Modp: return 3
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securemessage_PublicKeyType: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct Securemessage_SecureMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// Must contain a HeaderAndBody message
|
||||
var headerAndBody: Data {
|
||||
get {return _headerAndBody ?? Data()}
|
||||
set {_headerAndBody = newValue}
|
||||
}
|
||||
/// Returns true if `headerAndBody` has been explicitly set.
|
||||
var hasHeaderAndBody: Bool {return self._headerAndBody != nil}
|
||||
/// Clears the value of `headerAndBody`. Subsequent reads from it will return its default value.
|
||||
mutating func clearHeaderAndBody() {self._headerAndBody = nil}
|
||||
|
||||
/// Signature of header_and_body
|
||||
var signature: Data {
|
||||
get {return _signature ?? Data()}
|
||||
set {_signature = newValue}
|
||||
}
|
||||
/// Returns true if `signature` has been explicitly set.
|
||||
var hasSignature: Bool {return self._signature != nil}
|
||||
/// Clears the value of `signature`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSignature() {self._signature = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _headerAndBody: Data? = nil
|
||||
fileprivate var _signature: Data? = nil
|
||||
}
|
||||
|
||||
struct Securemessage_Header {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var signatureScheme: Securemessage_SigScheme {
|
||||
get {return _signatureScheme ?? .hmacSha256}
|
||||
set {_signatureScheme = newValue}
|
||||
}
|
||||
/// Returns true if `signatureScheme` has been explicitly set.
|
||||
var hasSignatureScheme: Bool {return self._signatureScheme != nil}
|
||||
/// Clears the value of `signatureScheme`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSignatureScheme() {self._signatureScheme = nil}
|
||||
|
||||
var encryptionScheme: Securemessage_EncScheme {
|
||||
get {return _encryptionScheme ?? .none}
|
||||
set {_encryptionScheme = newValue}
|
||||
}
|
||||
/// Returns true if `encryptionScheme` has been explicitly set.
|
||||
var hasEncryptionScheme: Bool {return self._encryptionScheme != nil}
|
||||
/// Clears the value of `encryptionScheme`. Subsequent reads from it will return its default value.
|
||||
mutating func clearEncryptionScheme() {self._encryptionScheme = nil}
|
||||
|
||||
/// Identifies the verification key
|
||||
var verificationKeyID: Data {
|
||||
get {return _verificationKeyID ?? Data()}
|
||||
set {_verificationKeyID = newValue}
|
||||
}
|
||||
/// Returns true if `verificationKeyID` has been explicitly set.
|
||||
var hasVerificationKeyID: Bool {return self._verificationKeyID != nil}
|
||||
/// Clears the value of `verificationKeyID`. Subsequent reads from it will return its default value.
|
||||
mutating func clearVerificationKeyID() {self._verificationKeyID = nil}
|
||||
|
||||
/// Identifies the decryption key
|
||||
var decryptionKeyID: Data {
|
||||
get {return _decryptionKeyID ?? Data()}
|
||||
set {_decryptionKeyID = newValue}
|
||||
}
|
||||
/// Returns true if `decryptionKeyID` has been explicitly set.
|
||||
var hasDecryptionKeyID: Bool {return self._decryptionKeyID != nil}
|
||||
/// Clears the value of `decryptionKeyID`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDecryptionKeyID() {self._decryptionKeyID = nil}
|
||||
|
||||
/// Encryption may use an IV
|
||||
var iv: Data {
|
||||
get {return _iv ?? Data()}
|
||||
set {_iv = newValue}
|
||||
}
|
||||
/// Returns true if `iv` has been explicitly set.
|
||||
var hasIv: Bool {return self._iv != nil}
|
||||
/// Clears the value of `iv`. Subsequent reads from it will return its default value.
|
||||
mutating func clearIv() {self._iv = nil}
|
||||
|
||||
/// Arbitrary per-protocol public data, to be sent with the plain-text header
|
||||
var publicMetadata: Data {
|
||||
get {return _publicMetadata ?? Data()}
|
||||
set {_publicMetadata = newValue}
|
||||
}
|
||||
/// Returns true if `publicMetadata` has been explicitly set.
|
||||
var hasPublicMetadata: Bool {return self._publicMetadata != nil}
|
||||
/// Clears the value of `publicMetadata`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicMetadata() {self._publicMetadata = nil}
|
||||
|
||||
/// The length of some associated data this is not sent in this SecureMessage,
|
||||
/// but which will be bound to the signature.
|
||||
var associatedDataLength: UInt32 {
|
||||
get {return _associatedDataLength ?? 0}
|
||||
set {_associatedDataLength = newValue}
|
||||
}
|
||||
/// Returns true if `associatedDataLength` has been explicitly set.
|
||||
var hasAssociatedDataLength: Bool {return self._associatedDataLength != nil}
|
||||
/// Clears the value of `associatedDataLength`. Subsequent reads from it will return its default value.
|
||||
mutating func clearAssociatedDataLength() {self._associatedDataLength = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _signatureScheme: Securemessage_SigScheme? = nil
|
||||
fileprivate var _encryptionScheme: Securemessage_EncScheme? = nil
|
||||
fileprivate var _verificationKeyID: Data? = nil
|
||||
fileprivate var _decryptionKeyID: Data? = nil
|
||||
fileprivate var _iv: Data? = nil
|
||||
fileprivate var _publicMetadata: Data? = nil
|
||||
fileprivate var _associatedDataLength: UInt32? = nil
|
||||
}
|
||||
|
||||
struct Securemessage_HeaderAndBody {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// Public data about this message (to be bound in the signature)
|
||||
var header: Securemessage_Header {
|
||||
get {return _header ?? Securemessage_Header()}
|
||||
set {_header = newValue}
|
||||
}
|
||||
/// Returns true if `header` has been explicitly set.
|
||||
var hasHeader: Bool {return self._header != nil}
|
||||
/// Clears the value of `header`. Subsequent reads from it will return its default value.
|
||||
mutating func clearHeader() {self._header = nil}
|
||||
|
||||
/// Payload data
|
||||
var body: Data {
|
||||
get {return _body ?? Data()}
|
||||
set {_body = newValue}
|
||||
}
|
||||
/// Returns true if `body` has been explicitly set.
|
||||
var hasBody: Bool {return self._body != nil}
|
||||
/// Clears the value of `body`. Subsequent reads from it will return its default value.
|
||||
mutating func clearBody() {self._body = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _header: Securemessage_Header? = nil
|
||||
fileprivate var _body: Data? = nil
|
||||
}
|
||||
|
||||
/// Must be kept wire-format compatible with HeaderAndBody. Provides the
|
||||
/// SecureMessage code with a consistent wire-format representation that
|
||||
/// remains stable irrespective of protobuf implementation choices. This
|
||||
/// low-level representation of a HeaderAndBody should not be used by
|
||||
/// any code outside of the SecureMessage library implementation/tests.
|
||||
struct Securemessage_HeaderAndBodyInternal {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// A raw (wire-format) byte encoding of a Header, suitable for hashing
|
||||
var header: Data {
|
||||
get {return _header ?? Data()}
|
||||
set {_header = newValue}
|
||||
}
|
||||
/// Returns true if `header` has been explicitly set.
|
||||
var hasHeader: Bool {return self._header != nil}
|
||||
/// Clears the value of `header`. Subsequent reads from it will return its default value.
|
||||
mutating func clearHeader() {self._header = nil}
|
||||
|
||||
/// Payload data
|
||||
var body: Data {
|
||||
get {return _body ?? Data()}
|
||||
set {_body = newValue}
|
||||
}
|
||||
/// Returns true if `body` has been explicitly set.
|
||||
var hasBody: Bool {return self._body != nil}
|
||||
/// Clears the value of `body`. Subsequent reads from it will return its default value.
|
||||
mutating func clearBody() {self._body = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _header: Data? = nil
|
||||
fileprivate var _body: Data? = nil
|
||||
}
|
||||
|
||||
/// A convenience proto for encoding NIST P-256 elliptic curve public keys
|
||||
struct Securemessage_EcP256PublicKey {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// x and y are encoded in big-endian two's complement (slightly wasteful)
|
||||
/// Client MUST verify (x,y) is a valid point on NIST P256
|
||||
var x: Data {
|
||||
get {return _x ?? Data()}
|
||||
set {_x = newValue}
|
||||
}
|
||||
/// Returns true if `x` has been explicitly set.
|
||||
var hasX: Bool {return self._x != nil}
|
||||
/// Clears the value of `x`. Subsequent reads from it will return its default value.
|
||||
mutating func clearX() {self._x = nil}
|
||||
|
||||
var y: Data {
|
||||
get {return _y ?? Data()}
|
||||
set {_y = newValue}
|
||||
}
|
||||
/// Returns true if `y` has been explicitly set.
|
||||
var hasY: Bool {return self._y != nil}
|
||||
/// Clears the value of `y`. Subsequent reads from it will return its default value.
|
||||
mutating func clearY() {self._y = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _x: Data? = nil
|
||||
fileprivate var _y: Data? = nil
|
||||
}
|
||||
|
||||
/// A convenience proto for encoding RSA public keys with small exponents
|
||||
struct Securemessage_SimpleRsaPublicKey {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// Encoded in big-endian two's complement
|
||||
var n: Data {
|
||||
get {return _n ?? Data()}
|
||||
set {_n = newValue}
|
||||
}
|
||||
/// Returns true if `n` has been explicitly set.
|
||||
var hasN: Bool {return self._n != nil}
|
||||
/// Clears the value of `n`. Subsequent reads from it will return its default value.
|
||||
mutating func clearN() {self._n = nil}
|
||||
|
||||
var e: Int32 {
|
||||
get {return _e ?? 65537}
|
||||
set {_e = newValue}
|
||||
}
|
||||
/// Returns true if `e` has been explicitly set.
|
||||
var hasE: Bool {return self._e != nil}
|
||||
/// Clears the value of `e`. Subsequent reads from it will return its default value.
|
||||
mutating func clearE() {self._e = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _n: Data? = nil
|
||||
fileprivate var _e: Int32? = nil
|
||||
}
|
||||
|
||||
/// A convenience proto for encoding Diffie-Hellman public keys,
|
||||
/// for use only when Elliptic Curve based key exchanges are not possible.
|
||||
/// (Note that the group parameters must be specified separately)
|
||||
struct Securemessage_DhPublicKey {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// Big-endian two's complement encoded group element
|
||||
var y: Data {
|
||||
get {return _y ?? Data()}
|
||||
set {_y = newValue}
|
||||
}
|
||||
/// Returns true if `y` has been explicitly set.
|
||||
var hasY: Bool {return self._y != nil}
|
||||
/// Clears the value of `y`. Subsequent reads from it will return its default value.
|
||||
mutating func clearY() {self._y = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _y: Data? = nil
|
||||
}
|
||||
|
||||
struct Securemessage_GenericPublicKey {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var type: Securemessage_PublicKeyType {
|
||||
get {return _type ?? .ecP256}
|
||||
set {_type = newValue}
|
||||
}
|
||||
/// Returns true if `type` has been explicitly set.
|
||||
var hasType: Bool {return self._type != nil}
|
||||
/// Clears the value of `type`. Subsequent reads from it will return its default value.
|
||||
mutating func clearType() {self._type = nil}
|
||||
|
||||
var ecP256PublicKey: Securemessage_EcP256PublicKey {
|
||||
get {return _ecP256PublicKey ?? Securemessage_EcP256PublicKey()}
|
||||
set {_ecP256PublicKey = newValue}
|
||||
}
|
||||
/// Returns true if `ecP256PublicKey` has been explicitly set.
|
||||
var hasEcP256PublicKey: Bool {return self._ecP256PublicKey != nil}
|
||||
/// Clears the value of `ecP256PublicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearEcP256PublicKey() {self._ecP256PublicKey = nil}
|
||||
|
||||
var rsa2048PublicKey: Securemessage_SimpleRsaPublicKey {
|
||||
get {return _rsa2048PublicKey ?? Securemessage_SimpleRsaPublicKey()}
|
||||
set {_rsa2048PublicKey = newValue}
|
||||
}
|
||||
/// Returns true if `rsa2048PublicKey` has been explicitly set.
|
||||
var hasRsa2048PublicKey: Bool {return self._rsa2048PublicKey != nil}
|
||||
/// Clears the value of `rsa2048PublicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearRsa2048PublicKey() {self._rsa2048PublicKey = nil}
|
||||
|
||||
/// Use only as a last resort
|
||||
var dh2048PublicKey: Securemessage_DhPublicKey {
|
||||
get {return _dh2048PublicKey ?? Securemessage_DhPublicKey()}
|
||||
set {_dh2048PublicKey = newValue}
|
||||
}
|
||||
/// Returns true if `dh2048PublicKey` has been explicitly set.
|
||||
var hasDh2048PublicKey: Bool {return self._dh2048PublicKey != nil}
|
||||
/// Clears the value of `dh2048PublicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDh2048PublicKey() {self._dh2048PublicKey = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _type: Securemessage_PublicKeyType? = nil
|
||||
fileprivate var _ecP256PublicKey: Securemessage_EcP256PublicKey? = nil
|
||||
fileprivate var _rsa2048PublicKey: Securemessage_SimpleRsaPublicKey? = nil
|
||||
fileprivate var _dh2048PublicKey: Securemessage_DhPublicKey? = nil
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
extension Securemessage_SigScheme: @unchecked Sendable {}
|
||||
extension Securemessage_EncScheme: @unchecked Sendable {}
|
||||
extension Securemessage_PublicKeyType: @unchecked Sendable {}
|
||||
extension Securemessage_SecureMessage: @unchecked Sendable {}
|
||||
extension Securemessage_Header: @unchecked Sendable {}
|
||||
extension Securemessage_HeaderAndBody: @unchecked Sendable {}
|
||||
extension Securemessage_HeaderAndBodyInternal: @unchecked Sendable {}
|
||||
extension Securemessage_EcP256PublicKey: @unchecked Sendable {}
|
||||
extension Securemessage_SimpleRsaPublicKey: @unchecked Sendable {}
|
||||
extension Securemessage_DhPublicKey: @unchecked Sendable {}
|
||||
extension Securemessage_GenericPublicKey: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "securemessage"
|
||||
|
||||
extension Securemessage_SigScheme: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "HMAC_SHA256"),
|
||||
2: .same(proto: "ECDSA_P256_SHA256"),
|
||||
3: .same(proto: "RSA2048_SHA256"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securemessage_EncScheme: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "NONE"),
|
||||
2: .same(proto: "AES_256_CBC"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securemessage_PublicKeyType: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "EC_P256"),
|
||||
2: .same(proto: "RSA2048"),
|
||||
3: .same(proto: "DH2048_MODP"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securemessage_SecureMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".SecureMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "header_and_body"),
|
||||
2: .same(proto: "signature"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._headerAndBody == nil {return false}
|
||||
if self._signature == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._headerAndBody) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._signature) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._headerAndBody {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._signature {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_SecureMessage, rhs: Securemessage_SecureMessage) -> Bool {
|
||||
if lhs._headerAndBody != rhs._headerAndBody {return false}
|
||||
if lhs._signature != rhs._signature {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_Header: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".Header"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "signature_scheme"),
|
||||
2: .standard(proto: "encryption_scheme"),
|
||||
3: .standard(proto: "verification_key_id"),
|
||||
4: .standard(proto: "decryption_key_id"),
|
||||
5: .same(proto: "iv"),
|
||||
6: .standard(proto: "public_metadata"),
|
||||
7: .standard(proto: "associated_data_length"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._signatureScheme == nil {return false}
|
||||
if self._encryptionScheme == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self._signatureScheme) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self._encryptionScheme) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self._verificationKeyID) }()
|
||||
case 4: try { try decoder.decodeSingularBytesField(value: &self._decryptionKeyID) }()
|
||||
case 5: try { try decoder.decodeSingularBytesField(value: &self._iv) }()
|
||||
case 6: try { try decoder.decodeSingularBytesField(value: &self._publicMetadata) }()
|
||||
case 7: try { try decoder.decodeSingularUInt32Field(value: &self._associatedDataLength) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._signatureScheme {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._encryptionScheme {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._verificationKeyID {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try { if let v = self._decryptionKeyID {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try { if let v = self._iv {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 5)
|
||||
} }()
|
||||
try { if let v = self._publicMetadata {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
try { if let v = self._associatedDataLength {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 7)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_Header, rhs: Securemessage_Header) -> Bool {
|
||||
if lhs._signatureScheme != rhs._signatureScheme {return false}
|
||||
if lhs._encryptionScheme != rhs._encryptionScheme {return false}
|
||||
if lhs._verificationKeyID != rhs._verificationKeyID {return false}
|
||||
if lhs._decryptionKeyID != rhs._decryptionKeyID {return false}
|
||||
if lhs._iv != rhs._iv {return false}
|
||||
if lhs._publicMetadata != rhs._publicMetadata {return false}
|
||||
if lhs._associatedDataLength != rhs._associatedDataLength {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_HeaderAndBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".HeaderAndBody"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "header"),
|
||||
2: .same(proto: "body"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._header == nil {return false}
|
||||
if self._body == nil {return false}
|
||||
if let v = self._header, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularMessageField(value: &self._header) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._body) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._header {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._body {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_HeaderAndBody, rhs: Securemessage_HeaderAndBody) -> Bool {
|
||||
if lhs._header != rhs._header {return false}
|
||||
if lhs._body != rhs._body {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_HeaderAndBodyInternal: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".HeaderAndBodyInternal"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "header"),
|
||||
2: .same(proto: "body"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._header == nil {return false}
|
||||
if self._body == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._header) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._body) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._header {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._body {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_HeaderAndBodyInternal, rhs: Securemessage_HeaderAndBodyInternal) -> Bool {
|
||||
if lhs._header != rhs._header {return false}
|
||||
if lhs._body != rhs._body {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_EcP256PublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".EcP256PublicKey"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "x"),
|
||||
2: .same(proto: "y"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._x == nil {return false}
|
||||
if self._y == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._x) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._y) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._x {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._y {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_EcP256PublicKey, rhs: Securemessage_EcP256PublicKey) -> Bool {
|
||||
if lhs._x != rhs._x {return false}
|
||||
if lhs._y != rhs._y {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_SimpleRsaPublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".SimpleRsaPublicKey"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "n"),
|
||||
2: .same(proto: "e"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._n == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._n) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self._e) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._n {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._e {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_SimpleRsaPublicKey, rhs: Securemessage_SimpleRsaPublicKey) -> Bool {
|
||||
if lhs._n != rhs._n {return false}
|
||||
if lhs._e != rhs._e {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_DhPublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".DhPublicKey"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "y"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._y == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._y) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._y {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_DhPublicKey, rhs: Securemessage_DhPublicKey) -> Bool {
|
||||
if lhs._y != rhs._y {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securemessage_GenericPublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".GenericPublicKey"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "type"),
|
||||
2: .standard(proto: "ec_p256_public_key"),
|
||||
3: .standard(proto: "rsa2048_public_key"),
|
||||
4: .standard(proto: "dh2048_public_key"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._type == nil {return false}
|
||||
if let v = self._ecP256PublicKey, !v.isInitialized {return false}
|
||||
if let v = self._rsa2048PublicKey, !v.isInitialized {return false}
|
||||
if let v = self._dh2048PublicKey, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self._type) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &self._ecP256PublicKey) }()
|
||||
case 3: try { try decoder.decodeSingularMessageField(value: &self._rsa2048PublicKey) }()
|
||||
case 4: try { try decoder.decodeSingularMessageField(value: &self._dh2048PublicKey) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._ecP256PublicKey {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._rsa2048PublicKey {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try { if let v = self._dh2048PublicKey {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securemessage_GenericPublicKey, rhs: Securemessage_GenericPublicKey) -> Bool {
|
||||
if lhs._type != rhs._type {return false}
|
||||
if lhs._ecP256PublicKey != rhs._ecP256PublicKey {return false}
|
||||
if lhs._rsa2048PublicKey != rhs._rsa2048PublicKey {return false}
|
||||
if lhs._dh2048PublicKey != rhs._dh2048PublicKey {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
735
NearDrop/Protobuf/ukey.pb.swift
Normal file
@@ -0,0 +1,735 @@
|
||||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: ukey.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
enum Securegcm_Ukey2HandshakeCipher: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
case reserved // = 0
|
||||
|
||||
/// NIST P-256 used for ECDH, SHA512 used for
|
||||
case p256Sha512 // = 100
|
||||
|
||||
/// commitment
|
||||
case curve25519Sha512 // = 200
|
||||
|
||||
init() {
|
||||
self = .reserved
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .reserved
|
||||
case 100: self = .p256Sha512
|
||||
case 200: self = .curve25519Sha512
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .reserved: return 0
|
||||
case .p256Sha512: return 100
|
||||
case .curve25519Sha512: return 200
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securegcm_Ukey2HandshakeCipher: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct Securegcm_Ukey2Message {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// Identifies message type
|
||||
var messageType: Securegcm_Ukey2Message.TypeEnum {
|
||||
get {return _messageType ?? .unknownDoNotUse}
|
||||
set {_messageType = newValue}
|
||||
}
|
||||
/// Returns true if `messageType` has been explicitly set.
|
||||
var hasMessageType: Bool {return self._messageType != nil}
|
||||
/// Clears the value of `messageType`. Subsequent reads from it will return its default value.
|
||||
mutating func clearMessageType() {self._messageType = nil}
|
||||
|
||||
/// Actual message, to be parsed according to
|
||||
var messageData: Data {
|
||||
get {return _messageData ?? Data()}
|
||||
set {_messageData = newValue}
|
||||
}
|
||||
/// Returns true if `messageData` has been explicitly set.
|
||||
var hasMessageData: Bool {return self._messageData != nil}
|
||||
/// Clears the value of `messageData`. Subsequent reads from it will return its default value.
|
||||
mutating func clearMessageData() {self._messageData = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
enum TypeEnum: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
case unknownDoNotUse // = 0
|
||||
case alert // = 1
|
||||
case clientInit // = 2
|
||||
case serverInit // = 3
|
||||
case clientFinish // = 4
|
||||
|
||||
init() {
|
||||
self = .unknownDoNotUse
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .unknownDoNotUse
|
||||
case 1: self = .alert
|
||||
case 2: self = .clientInit
|
||||
case 3: self = .serverInit
|
||||
case 4: self = .clientFinish
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .unknownDoNotUse: return 0
|
||||
case .alert: return 1
|
||||
case .clientInit: return 2
|
||||
case .serverInit: return 3
|
||||
case .clientFinish: return 4
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _messageType: Securegcm_Ukey2Message.TypeEnum? = nil
|
||||
fileprivate var _messageData: Data? = nil
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securegcm_Ukey2Message.TypeEnum: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct Securegcm_Ukey2Alert {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var type: Securegcm_Ukey2Alert.AlertType {
|
||||
get {return _type ?? .badMessage}
|
||||
set {_type = newValue}
|
||||
}
|
||||
/// Returns true if `type` has been explicitly set.
|
||||
var hasType: Bool {return self._type != nil}
|
||||
/// Clears the value of `type`. Subsequent reads from it will return its default value.
|
||||
mutating func clearType() {self._type = nil}
|
||||
|
||||
var errorMessage: String {
|
||||
get {return _errorMessage ?? String()}
|
||||
set {_errorMessage = newValue}
|
||||
}
|
||||
/// Returns true if `errorMessage` has been explicitly set.
|
||||
var hasErrorMessage: Bool {return self._errorMessage != nil}
|
||||
/// Clears the value of `errorMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearErrorMessage() {self._errorMessage = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
enum AlertType: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
|
||||
/// Framing errors
|
||||
case badMessage // = 1
|
||||
|
||||
/// message_type has an undefined value
|
||||
case badMessageType // = 2
|
||||
|
||||
/// message_type received does not correspond to
|
||||
case incorrectMessage // = 3
|
||||
|
||||
/// expected type at this stage of the protocol
|
||||
case badMessageData // = 4
|
||||
|
||||
/// ClientInit and ServerInit errors
|
||||
case badVersion // = 100
|
||||
|
||||
/// suitable version to speak with client.
|
||||
case badRandom // = 101
|
||||
|
||||
/// length
|
||||
case badHandshakeCipher // = 102
|
||||
|
||||
/// The next protocol is missing, unknown, or
|
||||
case badNextProtocol // = 103
|
||||
|
||||
/// unsupported
|
||||
case badPublicKey // = 104
|
||||
|
||||
/// Other errors
|
||||
case internalError // = 200
|
||||
|
||||
init() {
|
||||
self = .badMessage
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 1: self = .badMessage
|
||||
case 2: self = .badMessageType
|
||||
case 3: self = .incorrectMessage
|
||||
case 4: self = .badMessageData
|
||||
case 100: self = .badVersion
|
||||
case 101: self = .badRandom
|
||||
case 102: self = .badHandshakeCipher
|
||||
case 103: self = .badNextProtocol
|
||||
case 104: self = .badPublicKey
|
||||
case 200: self = .internalError
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .badMessage: return 1
|
||||
case .badMessageType: return 2
|
||||
case .incorrectMessage: return 3
|
||||
case .badMessageData: return 4
|
||||
case .badVersion: return 100
|
||||
case .badRandom: return 101
|
||||
case .badHandshakeCipher: return 102
|
||||
case .badNextProtocol: return 103
|
||||
case .badPublicKey: return 104
|
||||
case .internalError: return 200
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _type: Securegcm_Ukey2Alert.AlertType? = nil
|
||||
fileprivate var _errorMessage: String? = nil
|
||||
}
|
||||
|
||||
#if swift(>=4.2)
|
||||
|
||||
extension Securegcm_Ukey2Alert.AlertType: CaseIterable {
|
||||
// Support synthesized by the compiler.
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct Securegcm_Ukey2ClientInit {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// highest supported version for rollback
|
||||
var version: Int32 {
|
||||
get {return _version ?? 0}
|
||||
set {_version = newValue}
|
||||
}
|
||||
/// Returns true if `version` has been explicitly set.
|
||||
var hasVersion: Bool {return self._version != nil}
|
||||
/// Clears the value of `version`. Subsequent reads from it will return its default value.
|
||||
mutating func clearVersion() {self._version = nil}
|
||||
|
||||
/// protection
|
||||
var random: Data {
|
||||
get {return _random ?? Data()}
|
||||
set {_random = newValue}
|
||||
}
|
||||
/// Returns true if `random` has been explicitly set.
|
||||
var hasRandom: Bool {return self._random != nil}
|
||||
/// Clears the value of `random`. Subsequent reads from it will return its default value.
|
||||
mutating func clearRandom() {self._random = nil}
|
||||
|
||||
var cipherCommitments: [Securegcm_Ukey2ClientInit.CipherCommitment] = []
|
||||
|
||||
/// Next protocol that the client wants to speak.
|
||||
var nextProtocol: String {
|
||||
get {return _nextProtocol ?? String()}
|
||||
set {_nextProtocol = newValue}
|
||||
}
|
||||
/// Returns true if `nextProtocol` has been explicitly set.
|
||||
var hasNextProtocol: Bool {return self._nextProtocol != nil}
|
||||
/// Clears the value of `nextProtocol`. Subsequent reads from it will return its default value.
|
||||
mutating func clearNextProtocol() {self._nextProtocol = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
/// One commitment (hash of ClientFinished containing public key) per supported
|
||||
/// cipher
|
||||
struct CipherCommitment {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var handshakeCipher: Securegcm_Ukey2HandshakeCipher {
|
||||
get {return _handshakeCipher ?? .reserved}
|
||||
set {_handshakeCipher = newValue}
|
||||
}
|
||||
/// Returns true if `handshakeCipher` has been explicitly set.
|
||||
var hasHandshakeCipher: Bool {return self._handshakeCipher != nil}
|
||||
/// Clears the value of `handshakeCipher`. Subsequent reads from it will return its default value.
|
||||
mutating func clearHandshakeCipher() {self._handshakeCipher = nil}
|
||||
|
||||
var commitment: Data {
|
||||
get {return _commitment ?? Data()}
|
||||
set {_commitment = newValue}
|
||||
}
|
||||
/// Returns true if `commitment` has been explicitly set.
|
||||
var hasCommitment: Bool {return self._commitment != nil}
|
||||
/// Clears the value of `commitment`. Subsequent reads from it will return its default value.
|
||||
mutating func clearCommitment() {self._commitment = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _handshakeCipher: Securegcm_Ukey2HandshakeCipher? = nil
|
||||
fileprivate var _commitment: Data? = nil
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _version: Int32? = nil
|
||||
fileprivate var _random: Data? = nil
|
||||
fileprivate var _nextProtocol: String? = nil
|
||||
}
|
||||
|
||||
struct Securegcm_Ukey2ServerInit {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// highest supported version for rollback
|
||||
var version: Int32 {
|
||||
get {return _version ?? 0}
|
||||
set {_version = newValue}
|
||||
}
|
||||
/// Returns true if `version` has been explicitly set.
|
||||
var hasVersion: Bool {return self._version != nil}
|
||||
/// Clears the value of `version`. Subsequent reads from it will return its default value.
|
||||
mutating func clearVersion() {self._version = nil}
|
||||
|
||||
/// protection
|
||||
var random: Data {
|
||||
get {return _random ?? Data()}
|
||||
set {_random = newValue}
|
||||
}
|
||||
/// Returns true if `random` has been explicitly set.
|
||||
var hasRandom: Bool {return self._random != nil}
|
||||
/// Clears the value of `random`. Subsequent reads from it will return its default value.
|
||||
mutating func clearRandom() {self._random = nil}
|
||||
|
||||
/// Selected Cipher and corresponding public key
|
||||
var handshakeCipher: Securegcm_Ukey2HandshakeCipher {
|
||||
get {return _handshakeCipher ?? .reserved}
|
||||
set {_handshakeCipher = newValue}
|
||||
}
|
||||
/// Returns true if `handshakeCipher` has been explicitly set.
|
||||
var hasHandshakeCipher: Bool {return self._handshakeCipher != nil}
|
||||
/// Clears the value of `handshakeCipher`. Subsequent reads from it will return its default value.
|
||||
mutating func clearHandshakeCipher() {self._handshakeCipher = nil}
|
||||
|
||||
var publicKey: Data {
|
||||
get {return _publicKey ?? Data()}
|
||||
set {_publicKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicKey` has been explicitly set.
|
||||
var hasPublicKey: Bool {return self._publicKey != nil}
|
||||
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicKey() {self._publicKey = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _version: Int32? = nil
|
||||
fileprivate var _random: Data? = nil
|
||||
fileprivate var _handshakeCipher: Securegcm_Ukey2HandshakeCipher? = nil
|
||||
fileprivate var _publicKey: Data? = nil
|
||||
}
|
||||
|
||||
struct Securegcm_Ukey2ClientFinished {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// public key matching selected handshake
|
||||
var publicKey: Data {
|
||||
get {return _publicKey ?? Data()}
|
||||
set {_publicKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicKey` has been explicitly set.
|
||||
var hasPublicKey: Bool {return self._publicKey != nil}
|
||||
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicKey() {self._publicKey = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _publicKey: Data? = nil
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
extension Securegcm_Ukey2HandshakeCipher: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2Message: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2Message.TypeEnum: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2Alert: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2Alert.AlertType: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2ClientInit: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2ClientInit.CipherCommitment: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2ServerInit: @unchecked Sendable {}
|
||||
extension Securegcm_Ukey2ClientFinished: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "securegcm"
|
||||
|
||||
extension Securegcm_Ukey2HandshakeCipher: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "RESERVED"),
|
||||
100: .same(proto: "P256_SHA512"),
|
||||
200: .same(proto: "CURVE25519_SHA512"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2Message: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".Ukey2Message"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "message_type"),
|
||||
2: .standard(proto: "message_data"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self._messageType) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._messageData) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._messageType {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._messageData {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_Ukey2Message, rhs: Securegcm_Ukey2Message) -> Bool {
|
||||
if lhs._messageType != rhs._messageType {return false}
|
||||
if lhs._messageData != rhs._messageData {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2Message.TypeEnum: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "UNKNOWN_DO_NOT_USE"),
|
||||
1: .same(proto: "ALERT"),
|
||||
2: .same(proto: "CLIENT_INIT"),
|
||||
3: .same(proto: "SERVER_INIT"),
|
||||
4: .same(proto: "CLIENT_FINISH"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2Alert: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".Ukey2Alert"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "type"),
|
||||
2: .standard(proto: "error_message"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self._type) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self._errorMessage) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._errorMessage {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_Ukey2Alert, rhs: Securegcm_Ukey2Alert) -> Bool {
|
||||
if lhs._type != rhs._type {return false}
|
||||
if lhs._errorMessage != rhs._errorMessage {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2Alert.AlertType: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "BAD_MESSAGE"),
|
||||
2: .same(proto: "BAD_MESSAGE_TYPE"),
|
||||
3: .same(proto: "INCORRECT_MESSAGE"),
|
||||
4: .same(proto: "BAD_MESSAGE_DATA"),
|
||||
100: .same(proto: "BAD_VERSION"),
|
||||
101: .same(proto: "BAD_RANDOM"),
|
||||
102: .same(proto: "BAD_HANDSHAKE_CIPHER"),
|
||||
103: .same(proto: "BAD_NEXT_PROTOCOL"),
|
||||
104: .same(proto: "BAD_PUBLIC_KEY"),
|
||||
200: .same(proto: "INTERNAL_ERROR"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2ClientInit: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".Ukey2ClientInit"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "version"),
|
||||
2: .same(proto: "random"),
|
||||
3: .standard(proto: "cipher_commitments"),
|
||||
4: .standard(proto: "next_protocol"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self._version) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._random) }()
|
||||
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.cipherCommitments) }()
|
||||
case 4: try { try decoder.decodeSingularStringField(value: &self._nextProtocol) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._version {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._random {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
if !self.cipherCommitments.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.cipherCommitments, fieldNumber: 3)
|
||||
}
|
||||
try { if let v = self._nextProtocol {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_Ukey2ClientInit, rhs: Securegcm_Ukey2ClientInit) -> Bool {
|
||||
if lhs._version != rhs._version {return false}
|
||||
if lhs._random != rhs._random {return false}
|
||||
if lhs.cipherCommitments != rhs.cipherCommitments {return false}
|
||||
if lhs._nextProtocol != rhs._nextProtocol {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2ClientInit.CipherCommitment: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = Securegcm_Ukey2ClientInit.protoMessageName + ".CipherCommitment"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "handshake_cipher"),
|
||||
2: .same(proto: "commitment"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self._handshakeCipher) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._commitment) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._handshakeCipher {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._commitment {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_Ukey2ClientInit.CipherCommitment, rhs: Securegcm_Ukey2ClientInit.CipherCommitment) -> Bool {
|
||||
if lhs._handshakeCipher != rhs._handshakeCipher {return false}
|
||||
if lhs._commitment != rhs._commitment {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2ServerInit: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".Ukey2ServerInit"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "version"),
|
||||
2: .same(proto: "random"),
|
||||
3: .standard(proto: "handshake_cipher"),
|
||||
4: .standard(proto: "public_key"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularInt32Field(value: &self._version) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._random) }()
|
||||
case 3: try { try decoder.decodeSingularEnumField(value: &self._handshakeCipher) }()
|
||||
case 4: try { try decoder.decodeSingularBytesField(value: &self._publicKey) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._version {
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._random {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._handshakeCipher {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_Ukey2ServerInit, rhs: Securegcm_Ukey2ServerInit) -> Bool {
|
||||
if lhs._version != rhs._version {return false}
|
||||
if lhs._random != rhs._random {return false}
|
||||
if lhs._handshakeCipher != rhs._handshakeCipher {return false}
|
||||
if lhs._publicKey != rhs._publicKey {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Securegcm_Ukey2ClientFinished: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".Ukey2ClientFinished"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "public_key"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self._publicKey) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Securegcm_Ukey2ClientFinished, rhs: Securegcm_Ukey2ClientFinished) -> Bool {
|
||||
if lhs._publicKey != rhs._publicKey {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
1617
NearDrop/Protobuf/wire_format.pb.swift
Normal file
81
NearDrop/ProtobufSource/device_to_device_messages.proto
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package securegcm;
|
||||
|
||||
import "securemessage.proto";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.security.cryptauth.lib.securegcm";
|
||||
option java_outer_classname = "DeviceToDeviceMessagesProto";
|
||||
option objc_class_prefix = "SGCM";
|
||||
|
||||
// Used by protocols between devices
|
||||
message DeviceToDeviceMessage {
|
||||
// the payload of the message
|
||||
optional bytes message = 1;
|
||||
|
||||
// the sequence number of the message - must be increasing.
|
||||
optional int32 sequence_number = 2;
|
||||
}
|
||||
|
||||
// sent as the first message from initiator to responder
|
||||
// in an unauthenticated Diffie-Hellman Key Exchange
|
||||
message InitiatorHello {
|
||||
// The session public key to send to the responder
|
||||
optional securemessage.GenericPublicKey public_dh_key = 1;
|
||||
|
||||
// The protocol version
|
||||
optional int32 protocol_version = 2 [default = 0];
|
||||
}
|
||||
|
||||
// sent inside the header of the first message from the responder to the
|
||||
// initiator in an unauthenticated Diffie-Hellman Key Exchange
|
||||
message ResponderHello {
|
||||
// The session public key to send to the initiator
|
||||
optional securemessage.GenericPublicKey public_dh_key = 1;
|
||||
|
||||
// The protocol version
|
||||
optional int32 protocol_version = 2 [default = 0];
|
||||
}
|
||||
|
||||
// Type of curve
|
||||
enum Curve { ED_25519 = 1; }
|
||||
|
||||
// A convenience proto for encoding curve points in affine representation
|
||||
message EcPoint {
|
||||
required Curve curve = 1;
|
||||
|
||||
// x and y are encoded in big-endian two's complement
|
||||
// client MUST verify (x,y) is a valid point on the specified curve
|
||||
required bytes x = 2;
|
||||
required bytes y = 3;
|
||||
}
|
||||
|
||||
message SpakeHandshakeMessage {
|
||||
// Each flow in the protocol bumps this counter
|
||||
optional int32 flow_number = 1;
|
||||
|
||||
// Some (but not all) SPAKE flows send a point on an elliptic curve
|
||||
optional EcPoint ec_point = 2;
|
||||
|
||||
// Some (but not all) SPAKE flows send a hash value
|
||||
optional bytes hash_value = 3;
|
||||
|
||||
// The last flow of a SPAKE protocol can send an optional payload,
|
||||
// since the key exchange is already complete on the sender's side.
|
||||
optional bytes payload = 4;
|
||||
}
|
||||
403
NearDrop/ProtobufSource/offline_wire_formats.proto
Normal file
@@ -0,0 +1,403 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package location.nearby.connections;
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_outer_classname = "OfflineWireFormatsProto";
|
||||
option java_package = "com.google.location.nearby.connections.proto";
|
||||
option objc_class_prefix = "GNCP";
|
||||
|
||||
message OfflineFrame {
|
||||
enum Version {
|
||||
UNKNOWN_VERSION = 0;
|
||||
V1 = 1;
|
||||
}
|
||||
optional Version version = 1;
|
||||
|
||||
// Right now there's only 1 version, but if there are more, exactly one of
|
||||
// the following fields will be set.
|
||||
optional V1Frame v1 = 2;
|
||||
}
|
||||
|
||||
message V1Frame {
|
||||
enum FrameType {
|
||||
UNKNOWN_FRAME_TYPE = 0;
|
||||
CONNECTION_REQUEST = 1;
|
||||
CONNECTION_RESPONSE = 2;
|
||||
PAYLOAD_TRANSFER = 3;
|
||||
BANDWIDTH_UPGRADE_NEGOTIATION = 4;
|
||||
KEEP_ALIVE = 5;
|
||||
DISCONNECTION = 6;
|
||||
PAIRED_KEY_ENCRYPTION = 7;
|
||||
}
|
||||
optional FrameType type = 1;
|
||||
|
||||
// Exactly one of the following fields will be set.
|
||||
optional ConnectionRequestFrame connection_request = 2;
|
||||
optional ConnectionResponseFrame connection_response = 3;
|
||||
optional PayloadTransferFrame payload_transfer = 4;
|
||||
optional BandwidthUpgradeNegotiationFrame bandwidth_upgrade_negotiation = 5;
|
||||
optional KeepAliveFrame keep_alive = 6;
|
||||
optional DisconnectionFrame disconnection = 7;
|
||||
optional PairedKeyEncryptionFrame paired_key_encryption = 8;
|
||||
}
|
||||
|
||||
message ConnectionRequestFrame {
|
||||
// Should always match cs/symbol:location.nearby.proto.connections.Medium
|
||||
// LINT.IfChange
|
||||
enum Medium {
|
||||
UNKNOWN_MEDIUM = 0;
|
||||
MDNS = 1 [deprecated = true];
|
||||
BLUETOOTH = 2;
|
||||
WIFI_HOTSPOT = 3;
|
||||
BLE = 4;
|
||||
WIFI_LAN = 5;
|
||||
WIFI_AWARE = 6;
|
||||
NFC = 7;
|
||||
WIFI_DIRECT = 8;
|
||||
WEB_RTC = 9;
|
||||
BLE_L2CAP = 10;
|
||||
USB = 11;
|
||||
}
|
||||
// LINT.ThenChange(//depot/google3/third_party/nearby/proto/connections_enums.proto)
|
||||
|
||||
optional string endpoint_id = 1;
|
||||
optional string endpoint_name = 2;
|
||||
optional bytes handshake_data = 3;
|
||||
// A random number generated for each outgoing connection that is presently
|
||||
// used to act as a tiebreaker when 2 devices connect to each other
|
||||
// simultaneously; this can also be used for other initialization-scoped
|
||||
// things in the future.
|
||||
optional int32 nonce = 4;
|
||||
// The mediums this device supports upgrading to. This list should be filtered
|
||||
// by both the strategy and this device's individual limitations.
|
||||
repeated Medium mediums = 5;
|
||||
optional bytes endpoint_info = 6;
|
||||
optional MediumMetadata medium_metadata = 7;
|
||||
optional int32 keep_alive_interval_millis = 8;
|
||||
optional int32 keep_alive_timeout_millis = 9;
|
||||
// The type of {@link Device} object.
|
||||
optional int32 device_type = 10 [default = 0];
|
||||
// The bytes of serialized {@link Device} object.
|
||||
optional bytes device_info = 11;
|
||||
}
|
||||
|
||||
message ConnectionResponseFrame {
|
||||
// This doesn't need to send back endpoint_id and endpoint_name (like
|
||||
// the ConnectionRequestFrame does) because those have already been
|
||||
// transmitted out-of-band, at the time this endpoint was discovered.
|
||||
|
||||
// One of:
|
||||
//
|
||||
// - ConnectionsStatusCodes.STATUS_OK
|
||||
// - ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED.
|
||||
optional int32 status = 1 [deprecated = true];
|
||||
optional bytes handshake_data = 2;
|
||||
|
||||
// Used to replace the status integer parameter with a meaningful enum item.
|
||||
// Map ConnectionsStatusCodes.STATUS_OK to ACCEPT and
|
||||
// ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED to REJECT.
|
||||
// Flag: connection_replace_status_with_response_connectionResponseFrame
|
||||
enum ResponseStatus {
|
||||
UNKNOWN_RESPONSE_STATUS = 0;
|
||||
ACCEPT = 1;
|
||||
REJECT = 2;
|
||||
}
|
||||
optional ResponseStatus response = 3;
|
||||
optional OsInfo os_info = 4;
|
||||
// A bitmask value to indicate which medium supports Multiplex transmission
|
||||
// feature. Each supporting medium could utilize one bit starting from the
|
||||
// least significant bit in this field. eq. BT utilizes the LSB bit which 0x01
|
||||
// means bt supports multiplex while 0x00 means not. Refer to ClientProxy.java
|
||||
// for the bit usages.
|
||||
optional int32 multiplex_socket_bitmask = 5;
|
||||
optional int32 nearby_connections_version = 6;
|
||||
}
|
||||
|
||||
message PayloadTransferFrame {
|
||||
enum PacketType {
|
||||
UNKNOWN_PACKET_TYPE = 0;
|
||||
DATA = 1;
|
||||
CONTROL = 2;
|
||||
}
|
||||
|
||||
message PayloadHeader {
|
||||
enum PayloadType {
|
||||
UNKNOWN_PAYLOAD_TYPE = 0;
|
||||
BYTES = 1;
|
||||
FILE = 2;
|
||||
STREAM = 3;
|
||||
}
|
||||
optional int64 id = 1;
|
||||
optional PayloadType type = 2;
|
||||
optional int64 total_size = 3;
|
||||
optional bool is_sensitive = 4;
|
||||
optional string file_name = 5;
|
||||
optional string parent_folder = 6;
|
||||
}
|
||||
|
||||
// Accompanies DATA packets.
|
||||
message PayloadChunk {
|
||||
enum Flags {
|
||||
LAST_CHUNK = 0x1;
|
||||
}
|
||||
optional int32 flags = 1;
|
||||
optional int64 offset = 2;
|
||||
optional bytes body = 3;
|
||||
}
|
||||
|
||||
// Accompanies CONTROL packets.
|
||||
message ControlMessage {
|
||||
enum EventType {
|
||||
UNKNOWN_EVENT_TYPE = 0;
|
||||
PAYLOAD_ERROR = 1;
|
||||
PAYLOAD_CANCELED = 2;
|
||||
PAYLOAD_RECEIVED_ACK = 3;
|
||||
}
|
||||
|
||||
optional EventType event = 1;
|
||||
optional int64 offset = 2;
|
||||
}
|
||||
|
||||
optional PacketType packet_type = 1;
|
||||
optional PayloadHeader payload_header = 2;
|
||||
|
||||
// Exactly one of the following fields will be set, depending on the type.
|
||||
optional PayloadChunk payload_chunk = 3;
|
||||
optional ControlMessage control_message = 4;
|
||||
}
|
||||
|
||||
message BandwidthUpgradeNegotiationFrame {
|
||||
enum EventType {
|
||||
UNKNOWN_EVENT_TYPE = 0;
|
||||
UPGRADE_PATH_AVAILABLE = 1;
|
||||
LAST_WRITE_TO_PRIOR_CHANNEL = 2;
|
||||
SAFE_TO_CLOSE_PRIOR_CHANNEL = 3;
|
||||
CLIENT_INTRODUCTION = 4;
|
||||
UPGRADE_FAILURE = 5;
|
||||
CLIENT_INTRODUCTION_ACK = 6;
|
||||
}
|
||||
|
||||
// Accompanies UPGRADE_PATH_AVAILABLE and UPGRADE_FAILURE events.
|
||||
message UpgradePathInfo {
|
||||
// Should always match cs/symbol:location.nearby.proto.connections.Medium
|
||||
enum Medium {
|
||||
UNKNOWN_MEDIUM = 0;
|
||||
MDNS = 1 [deprecated = true];
|
||||
BLUETOOTH = 2;
|
||||
WIFI_HOTSPOT = 3;
|
||||
BLE = 4;
|
||||
WIFI_LAN = 5;
|
||||
WIFI_AWARE = 6;
|
||||
NFC = 7;
|
||||
WIFI_DIRECT = 8;
|
||||
WEB_RTC = 9;
|
||||
// 10 is reserved.
|
||||
USB = 11;
|
||||
}
|
||||
|
||||
// Accompanies Medium.WIFI_HOTSPOT.
|
||||
message WifiHotspotCredentials {
|
||||
optional string ssid = 1;
|
||||
optional string password = 2;
|
||||
optional int32 port = 3;
|
||||
optional string gateway = 4 [default = "0.0.0.0"];
|
||||
// This field can be a band or frequency
|
||||
optional int32 frequency = 5 [default = -1];
|
||||
}
|
||||
|
||||
// Accompanies Medium.WIFI_LAN.
|
||||
message WifiLanSocket {
|
||||
optional bytes ip_address = 1;
|
||||
optional int32 wifi_port = 2;
|
||||
}
|
||||
|
||||
// Accompanies Medium.BLUETOOTH.
|
||||
message BluetoothCredentials {
|
||||
optional string service_name = 1;
|
||||
optional string mac_address = 2;
|
||||
}
|
||||
|
||||
// Accompanies Medium.WIFI_AWARE.
|
||||
message WifiAwareCredentials {
|
||||
optional string service_id = 1;
|
||||
optional bytes service_info = 2;
|
||||
optional string password = 3;
|
||||
}
|
||||
|
||||
// Accompanies Medium.WIFI_DIRECT.
|
||||
message WifiDirectCredentials {
|
||||
optional string ssid = 1;
|
||||
optional string password = 2;
|
||||
optional int32 port = 3;
|
||||
optional int32 frequency = 4;
|
||||
optional string gateway = 5 [default = "0.0.0.0"];
|
||||
}
|
||||
|
||||
// Accompanies Medium.WEB_RTC
|
||||
message WebRtcCredentials {
|
||||
optional string peer_id = 1;
|
||||
optional LocationHint location_hint = 2;
|
||||
}
|
||||
|
||||
optional Medium medium = 1;
|
||||
|
||||
// Exactly one of the following fields will be set.
|
||||
optional WifiHotspotCredentials wifi_hotspot_credentials = 2;
|
||||
optional WifiLanSocket wifi_lan_socket = 3;
|
||||
optional BluetoothCredentials bluetooth_credentials = 4;
|
||||
optional WifiAwareCredentials wifi_aware_credentials = 5;
|
||||
optional WifiDirectCredentials wifi_direct_credentials = 6;
|
||||
optional WebRtcCredentials web_rtc_credentials = 8;
|
||||
|
||||
// Disable Encryption for this upgrade medium to improve throughput.
|
||||
optional bool supports_disabling_encryption = 7;
|
||||
|
||||
// An ack will be sent after the CLIENT_INTRODUCTION frame.
|
||||
optional bool supports_client_introduction_ack = 9;
|
||||
}
|
||||
|
||||
// Accompanies CLIENT_INTRODUCTION events.
|
||||
message ClientIntroduction {
|
||||
optional string endpoint_id = 1;
|
||||
optional bool supports_disabling_encryption = 2;
|
||||
}
|
||||
|
||||
// Accompanies CLIENT_INTRODUCTION_ACK events.
|
||||
message ClientIntroductionAck {}
|
||||
|
||||
optional EventType event_type = 1;
|
||||
|
||||
// Exactly one of the following fields will be set.
|
||||
optional UpgradePathInfo upgrade_path_info = 2;
|
||||
optional ClientIntroduction client_introduction = 3;
|
||||
optional ClientIntroductionAck client_introduction_ack = 4;
|
||||
}
|
||||
|
||||
message KeepAliveFrame {
|
||||
// And ack will be sent after receiving KEEP_ALIVE frame.
|
||||
optional bool ack = 1;
|
||||
}
|
||||
|
||||
// Informs the remote side to immediately severe the socket connection.
|
||||
// Used in bandwidth upgrades to get around a race condition, but may be used
|
||||
// in other situations to trigger a faster disconnection event than waiting for
|
||||
// socket closed on the remote side.
|
||||
message DisconnectionFrame {
|
||||
// Apply safe-to-disconnect protocol if true.
|
||||
optional bool request_safe_to_disconnect = 1;
|
||||
|
||||
// Ack of receiving Disconnection frame will be sent to the sender
|
||||
// frame.
|
||||
optional bool ack_safe_to_disconnect = 2;
|
||||
}
|
||||
|
||||
// A paired key encryption packet sent between devices, contains signed data.
|
||||
message PairedKeyEncryptionFrame {
|
||||
// The encrypted data (raw authentication token for the established
|
||||
// connection) in byte array format.
|
||||
optional bytes signed_data = 1;
|
||||
}
|
||||
|
||||
message MediumMetadata {
|
||||
// True if local device supports 5GHz.
|
||||
optional bool supports_5_ghz = 1;
|
||||
// WiFi LAN BSSID, in the form of a six-byte MAC address: XX:XX:XX:XX:XX:XX
|
||||
optional string bssid = 2;
|
||||
// IP address, in network byte order: the highest order byte of the address is
|
||||
// in byte[0].
|
||||
optional bytes ip_address = 3;
|
||||
// True if local device supports 6GHz.
|
||||
optional bool supports_6_ghz = 4;
|
||||
// True if local device has mobile radio.
|
||||
optional bool mobile_radio = 5;
|
||||
// The frequency of the WiFi LAN AP(in MHz). Or -1 is not associated with an
|
||||
// AP over WiFi, -2 represents the active network uses an Ethernet transport.
|
||||
optional int32 ap_frequency = 6 [default = -1];
|
||||
// Available channels on the local device.
|
||||
optional AvailableChannels available_channels = 7;
|
||||
// Usable WiFi Direct client channels on the local device.
|
||||
optional WifiDirectCliUsableChannels wifi_direct_cli_usable_channels = 8;
|
||||
// Usable WiFi LAN channels on the local device.
|
||||
optional WifiLanUsableChannels wifi_lan_usable_channels = 9;
|
||||
// Usable WiFi Aware channels on the local device.
|
||||
optional WifiAwareUsableChannels wifi_aware_usable_channels = 10;
|
||||
// Usable WiFi Hotspot STA channels on the local device.
|
||||
optional WifiHotspotStaUsableChannels wifi_hotspot_sta_usable_channels = 11;
|
||||
}
|
||||
|
||||
// Available channels on the local device.
|
||||
message AvailableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi Direct client channels on the local device.
|
||||
message WifiDirectCliUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi LAN channels on the local device.
|
||||
message WifiLanUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi Aware channels on the local device.
|
||||
message WifiAwareUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi Hotspot STA channels on the local device.
|
||||
message WifiHotspotStaUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// LocationHint is used to specify a location as well as format.
|
||||
message LocationHint {
|
||||
// Location is the location, provided in the format specified by format.
|
||||
optional string location = 1;
|
||||
|
||||
// the format of location.
|
||||
optional LocationStandard.Format format = 2;
|
||||
}
|
||||
|
||||
message LocationStandard {
|
||||
enum Format {
|
||||
UNKNOWN = 0;
|
||||
// E164 country codes:
|
||||
// https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
||||
// e.g. +1 for USA
|
||||
E164_CALLING = 1;
|
||||
|
||||
// ISO 3166-1 alpha-2 country codes:
|
||||
// https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
||||
ISO_3166_1_ALPHA_2 = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Device capability for OS information.
|
||||
message OsInfo {
|
||||
enum OsType {
|
||||
UNKNOWN_OS_TYPE = 0;
|
||||
ANDROID = 1;
|
||||
CHROME_OS = 2;
|
||||
WINDOWS = 3;
|
||||
APPLE = 4;
|
||||
LINUX = 100; // g3 test environment
|
||||
}
|
||||
|
||||
optional OsType type = 1;
|
||||
}
|
||||
308
NearDrop/ProtobufSource/securegcm.proto
Normal file
@@ -0,0 +1,308 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package securegcm;
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.security.cryptauth.lib.securegcm";
|
||||
option java_outer_classname = "SecureGcmProto";
|
||||
option objc_class_prefix = "SGCM";
|
||||
|
||||
// Message used only during enrollment
|
||||
// Field numbers should be kept in sync with DeviceInfo in:
|
||||
// java/com/google/security/cryptauth/backend/services/common/common.proto
|
||||
message GcmDeviceInfo {
|
||||
// This field's name does not match the one in DeviceInfo for legacy reasons.
|
||||
// Consider using long_device_id and device_type instead when enrolling
|
||||
// non-android devices.
|
||||
optional fixed64 android_device_id = 1;
|
||||
|
||||
// Used for device_address of DeviceInfo field 2, but for GCM capable devices.
|
||||
optional bytes gcm_registration_id = 102;
|
||||
|
||||
// Used for device_address of DeviceInfo field 2, but for iOS devices.
|
||||
optional bytes apn_registration_id = 202;
|
||||
|
||||
// Does the user have notifications enabled for the given device address.
|
||||
optional bool notification_enabled = 203 [default = true];
|
||||
|
||||
// Used for device_address of DeviceInfo field 2, a Bluetooth Mac address for
|
||||
// the device (e.g., to be used with EasyUnlock)
|
||||
optional string bluetooth_mac_address = 302;
|
||||
|
||||
// SHA-256 hash of the device master key (from the key exchange).
|
||||
// Differs from DeviceInfo field 3, which contains the actual master key.
|
||||
optional bytes device_master_key_hash = 103;
|
||||
|
||||
// A SecureMessage.EcP256PublicKey
|
||||
required bytes user_public_key = 4;
|
||||
|
||||
// device's model name
|
||||
// (e.g., an android.os.Build.MODEL or UIDevice.model)
|
||||
optional string device_model = 7;
|
||||
|
||||
// device's locale
|
||||
optional string locale = 8;
|
||||
|
||||
// The handle for user_public_key (and implicitly, a master key)
|
||||
optional bytes key_handle = 9;
|
||||
|
||||
// The initial counter value for the device, sent by the device
|
||||
optional int64 counter = 12 [default = 0];
|
||||
|
||||
// The Operating System version on the device
|
||||
// (e.g., an android.os.Build.DISPLAY or UIDevice.systemVersion)
|
||||
optional string device_os_version = 13;
|
||||
|
||||
// The Operating System version number on the device
|
||||
// (e.g., an android.os.Build.VERSION.SDK_INT)
|
||||
optional int64 device_os_version_code = 14;
|
||||
|
||||
// The Operating System release on the device
|
||||
// (e.g., an android.os.Build.VERSION.RELEASE)
|
||||
optional string device_os_release = 15;
|
||||
|
||||
// The Operating System codename on the device
|
||||
// (e.g., an android.os.Build.VERSION.CODENAME or UIDevice.systemName)
|
||||
optional string device_os_codename = 16;
|
||||
|
||||
// The software version running on the device
|
||||
// (e.g., Authenticator app version string)
|
||||
optional string device_software_version = 17;
|
||||
|
||||
// The software version number running on the device
|
||||
// (e.g., Authenticator app version code)
|
||||
optional int64 device_software_version_code = 18;
|
||||
|
||||
// Software package information if applicable
|
||||
// (e.g., com.google.android.apps.authenticator2)
|
||||
optional string device_software_package = 19;
|
||||
|
||||
// Size of the display in thousandths of an inch (e.g., 7000 mils = 7 in)
|
||||
optional int32 device_display_diagonal_mils = 22;
|
||||
|
||||
// For Authzen capable devices, their Authzen protocol version
|
||||
optional int32 device_authzen_version = 24;
|
||||
|
||||
// Not all devices have device identifiers that fit in 64 bits.
|
||||
optional bytes long_device_id = 29;
|
||||
|
||||
// The device manufacturer name
|
||||
// (e.g., android.os.Build.MANUFACTURER)
|
||||
optional string device_manufacturer = 31;
|
||||
|
||||
// Used to indicate which type of device this is.
|
||||
optional DeviceType device_type = 32 [default = ANDROID];
|
||||
|
||||
// Fields corresponding to screenlock type/features and hardware features
|
||||
// should be numbered in the 400 range.
|
||||
|
||||
// Is this device using a secure screenlock (e.g., pattern or pin unlock)
|
||||
optional bool using_secure_screenlock = 400 [default = false];
|
||||
|
||||
// Is auto-unlocking the screenlock (e.g., when at "home") supported?
|
||||
optional bool auto_unlock_screenlock_supported = 401 [default = false];
|
||||
|
||||
// Is auto-unlocking the screenlock (e.g., when at "home") enabled?
|
||||
optional bool auto_unlock_screenlock_enabled = 402 [default = false];
|
||||
|
||||
// Does the device have a Bluetooth (classic) radio?
|
||||
optional bool bluetooth_radio_supported = 403 [default = false];
|
||||
|
||||
// Is the Bluetooth (classic) radio on?
|
||||
optional bool bluetooth_radio_enabled = 404 [default = false];
|
||||
|
||||
// Does the device hardware support a mobile data connection?
|
||||
optional bool mobile_data_supported = 405 [default = false];
|
||||
|
||||
// Does the device support tethering?
|
||||
optional bool tethering_supported = 406 [default = false];
|
||||
|
||||
// Does the device have a BLE radio?
|
||||
optional bool ble_radio_supported = 407 [default = false];
|
||||
|
||||
// Is the device a "Pixel Experience" Android device?
|
||||
optional bool pixel_experience = 408 [default = false];
|
||||
|
||||
// Is the device running in the ARC++ container on a chromebook?
|
||||
optional bool arc_plus_plus = 409 [default = false];
|
||||
|
||||
// Is the value set in |using_secure_screenlock| reliable? On some Android
|
||||
// devices, the platform API to get the screenlock state is not trustworthy.
|
||||
// See b/32212161.
|
||||
optional bool is_screenlock_state_flaky = 410 [default = false];
|
||||
|
||||
// A list of multi-device software features supported by the device.
|
||||
repeated SoftwareFeature supported_software_features = 411;
|
||||
|
||||
// A list of multi-device software features currently enabled (active) on the
|
||||
// device.
|
||||
repeated SoftwareFeature enabled_software_features = 412;
|
||||
|
||||
// The enrollment session id this is sent with
|
||||
optional bytes enrollment_session_id = 1000;
|
||||
|
||||
// A copy of the user's OAuth token
|
||||
optional string oauth_token = 1001;
|
||||
}
|
||||
|
||||
// This enum is used by iOS devices as values for device_display_diagonal_mils
|
||||
// in GcmDeviceInfo. There is no good way to calculate it on those devices.
|
||||
enum AppleDeviceDiagonalMils {
|
||||
// This is the mils diagonal on an iPhone 5.
|
||||
APPLE_PHONE = 4000;
|
||||
// This is the mils diagonal on an iPad mini.
|
||||
APPLE_PAD = 7900;
|
||||
}
|
||||
|
||||
// This should be kept in sync with DeviceType in:
|
||||
// java/com/google/security/cryptauth/backend/services/common/common_enums.proto
|
||||
enum DeviceType {
|
||||
UNKNOWN = 0;
|
||||
ANDROID = 1;
|
||||
CHROME = 2;
|
||||
IOS = 3;
|
||||
BROWSER = 4;
|
||||
OSX = 5;
|
||||
}
|
||||
|
||||
// MultiDevice features which may be supported and enabled on a device. See
|
||||
enum SoftwareFeature {
|
||||
UNKNOWN_FEATURE = 0;
|
||||
BETTER_TOGETHER_HOST = 1;
|
||||
BETTER_TOGETHER_CLIENT = 2;
|
||||
EASY_UNLOCK_HOST = 3;
|
||||
EASY_UNLOCK_CLIENT = 4;
|
||||
MAGIC_TETHER_HOST = 5;
|
||||
MAGIC_TETHER_CLIENT = 6;
|
||||
SMS_CONNECT_HOST = 7;
|
||||
SMS_CONNECT_CLIENT = 8;
|
||||
}
|
||||
|
||||
// A list of "reasons" that can be provided for calling server-side APIs.
|
||||
// This is particularly important for calls that can be triggered by different
|
||||
// kinds of events. Please try to keep reasons as generic as possible, so that
|
||||
// codes can be re-used by various callers in a sensible fashion.
|
||||
enum InvocationReason {
|
||||
REASON_UNKNOWN = 0;
|
||||
// First run of the software package invoking this call
|
||||
REASON_INITIALIZATION = 1;
|
||||
// Ordinary periodic actions (e.g. monthly master key rotation)
|
||||
REASON_PERIODIC = 2;
|
||||
// Slow-cycle periodic action (e.g. yearly keypair rotation???)
|
||||
REASON_SLOW_PERIODIC = 3;
|
||||
// Fast-cycle periodic action (e.g. daily sync for Smart Lock users)
|
||||
REASON_FAST_PERIODIC = 4;
|
||||
// Expired state (e.g. expired credentials, or cached entries) was detected
|
||||
REASON_EXPIRATION = 5;
|
||||
// An unexpected protocol failure occurred (so attempting to repair state)
|
||||
REASON_FAILURE_RECOVERY = 6;
|
||||
// A new account has been added to the device
|
||||
REASON_NEW_ACCOUNT = 7;
|
||||
// An existing account on the device has been changed
|
||||
REASON_CHANGED_ACCOUNT = 8;
|
||||
// The user toggled the state of a feature (e.g. Smart Lock enabled via BT)
|
||||
REASON_FEATURE_TOGGLED = 9;
|
||||
// A "push" from the server caused this action (e.g. a sync tickle)
|
||||
REASON_SERVER_INITIATED = 10;
|
||||
// A local address change triggered this (e.g. GCM registration id changed)
|
||||
REASON_ADDRESS_CHANGE = 11;
|
||||
// A software update has triggered this
|
||||
REASON_SOFTWARE_UPDATE = 12;
|
||||
// A manual action by the user triggered this (e.g. commands sent via adb)
|
||||
REASON_MANUAL = 13;
|
||||
// A custom key has been invalidated on the device (e.g. screen lock is
|
||||
// disabled).
|
||||
REASON_CUSTOM_KEY_INVALIDATION = 14;
|
||||
// Periodic action triggered by auth_proximity
|
||||
REASON_PROXIMITY_PERIODIC = 15;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
ENROLLMENT = 0;
|
||||
TICKLE = 1;
|
||||
TX_REQUEST = 2;
|
||||
TX_REPLY = 3;
|
||||
TX_SYNC_REQUEST = 4;
|
||||
TX_SYNC_RESPONSE = 5;
|
||||
TX_PING = 6;
|
||||
DEVICE_INFO_UPDATE = 7;
|
||||
TX_CANCEL_REQUEST = 8;
|
||||
|
||||
// DEPRECATED (can be re-used after Aug 2015)
|
||||
PROXIMITYAUTH_PAIRING = 10;
|
||||
|
||||
// The kind of identity assertion generated by a "GCM V1" device (i.e.,
|
||||
// an Android phone that has registered with us a public and a symmetric
|
||||
// key)
|
||||
GCMV1_IDENTITY_ASSERTION = 11;
|
||||
|
||||
// Device-to-device communications are protected by an unauthenticated
|
||||
// Diffie-Hellman exchange. The InitiatorHello message is simply the
|
||||
// initiator's public DH key, and is not encoded as a SecureMessage, so
|
||||
// it doesn't have a tag.
|
||||
// The ResponderHello message (which is sent by the responder
|
||||
// to the initiator), on the other hand, carries a payload that is protected
|
||||
// by the derived shared key. It also contains the responder's
|
||||
// public DH key. ResponderHelloAndPayload messages have the
|
||||
// DEVICE_TO_DEVICE_RESPONDER_HELLO tag.
|
||||
DEVICE_TO_DEVICE_RESPONDER_HELLO_PAYLOAD = 12;
|
||||
|
||||
// Device-to-device communications are protected by an unauthenticated
|
||||
// Diffie-Hellman exchange. Once the initiator and responder
|
||||
// agree on a shared key (through Diffie-Hellman), they will use messages
|
||||
// tagged with DEVICE_TO_DEVICE_MESSAGE to exchange data.
|
||||
DEVICE_TO_DEVICE_MESSAGE = 13;
|
||||
|
||||
// Notification to let a device know it should contact a nearby device.
|
||||
DEVICE_PROXIMITY_CALLBACK = 14;
|
||||
|
||||
// Device-to-device communications are protected by an unauthenticated
|
||||
// Diffie-Hellman exchange. During device-to-device authentication, the first
|
||||
// message from initiator (the challenge) is signed and put into the payload
|
||||
// of the message sent back to the initiator.
|
||||
UNLOCK_KEY_SIGNED_CHALLENGE = 15;
|
||||
|
||||
// Specialty (corp only) features
|
||||
LOGIN_NOTIFICATION = 101;
|
||||
}
|
||||
|
||||
message GcmMetadata {
|
||||
required Type type = 1;
|
||||
optional int32 version = 2 [default = 0];
|
||||
}
|
||||
|
||||
message Tickle {
|
||||
// Time after which this tickle should expire
|
||||
optional fixed64 expiry_time = 1;
|
||||
}
|
||||
|
||||
message LoginNotificationInfo {
|
||||
// Time at which the server received the login notification request.
|
||||
optional fixed64 creation_time = 2;
|
||||
|
||||
// Must correspond to user_id in LoginNotificationRequest, if set.
|
||||
optional string email = 3;
|
||||
|
||||
// Host where the user's credentials were used to login, if meaningful.
|
||||
optional string host = 4;
|
||||
|
||||
// Location from where the user's credentials were used, if meaningful.
|
||||
optional string source = 5;
|
||||
|
||||
// Type of login, e.g. ssh, gnome-screensaver, or web.
|
||||
optional string event_type = 6;
|
||||
}
|
||||
126
NearDrop/ProtobufSource/securemessage.proto
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Proto definitions for SecureMessage format
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package securemessage;
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.security.cryptauth.lib.securemessage";
|
||||
option java_outer_classname = "SecureMessageProto";
|
||||
option objc_class_prefix = "SMSG";
|
||||
|
||||
message SecureMessage {
|
||||
// Must contain a HeaderAndBody message
|
||||
required bytes header_and_body = 1;
|
||||
// Signature of header_and_body
|
||||
required bytes signature = 2;
|
||||
}
|
||||
|
||||
// Supported "signature" schemes (both symmetric key and public key based)
|
||||
enum SigScheme {
|
||||
HMAC_SHA256 = 1;
|
||||
ECDSA_P256_SHA256 = 2;
|
||||
// Not recommended -- use ECDSA_P256_SHA256 instead
|
||||
RSA2048_SHA256 = 3;
|
||||
}
|
||||
|
||||
// Supported encryption schemes
|
||||
enum EncScheme {
|
||||
// No encryption
|
||||
NONE = 1;
|
||||
AES_256_CBC = 2;
|
||||
}
|
||||
|
||||
message Header {
|
||||
required SigScheme signature_scheme = 1;
|
||||
required EncScheme encryption_scheme = 2;
|
||||
// Identifies the verification key
|
||||
optional bytes verification_key_id = 3;
|
||||
// Identifies the decryption key
|
||||
optional bytes decryption_key_id = 4;
|
||||
// Encryption may use an IV
|
||||
optional bytes iv = 5;
|
||||
// Arbitrary per-protocol public data, to be sent with the plain-text header
|
||||
optional bytes public_metadata = 6;
|
||||
// The length of some associated data this is not sent in this SecureMessage,
|
||||
// but which will be bound to the signature.
|
||||
optional uint32 associated_data_length = 7 [default = 0];
|
||||
}
|
||||
|
||||
message HeaderAndBody {
|
||||
// Public data about this message (to be bound in the signature)
|
||||
required Header header = 1;
|
||||
// Payload data
|
||||
required bytes body = 2;
|
||||
}
|
||||
|
||||
// Must be kept wire-format compatible with HeaderAndBody. Provides the
|
||||
// SecureMessage code with a consistent wire-format representation that
|
||||
// remains stable irrespective of protobuf implementation choices. This
|
||||
// low-level representation of a HeaderAndBody should not be used by
|
||||
// any code outside of the SecureMessage library implementation/tests.
|
||||
message HeaderAndBodyInternal {
|
||||
// A raw (wire-format) byte encoding of a Header, suitable for hashing
|
||||
required bytes header = 1;
|
||||
// Payload data
|
||||
required bytes body = 2;
|
||||
}
|
||||
|
||||
// -------
|
||||
// The remainder of the messages defined here are provided only for
|
||||
// convenience. They are not needed for SecureMessage proper, but are
|
||||
// commonly useful wherever SecureMessage might be applied.
|
||||
// -------
|
||||
|
||||
// A list of supported public key types
|
||||
enum PublicKeyType {
|
||||
EC_P256 = 1;
|
||||
RSA2048 = 2;
|
||||
// 2048-bit MODP group 14, from RFC 3526
|
||||
DH2048_MODP = 3;
|
||||
}
|
||||
|
||||
// A convenience proto for encoding NIST P-256 elliptic curve public keys
|
||||
message EcP256PublicKey {
|
||||
// x and y are encoded in big-endian two's complement (slightly wasteful)
|
||||
// Client MUST verify (x,y) is a valid point on NIST P256
|
||||
required bytes x = 1;
|
||||
required bytes y = 2;
|
||||
}
|
||||
|
||||
// A convenience proto for encoding RSA public keys with small exponents
|
||||
message SimpleRsaPublicKey {
|
||||
// Encoded in big-endian two's complement
|
||||
required bytes n = 1;
|
||||
optional int32 e = 2 [default = 65537];
|
||||
}
|
||||
|
||||
// A convenience proto for encoding Diffie-Hellman public keys,
|
||||
// for use only when Elliptic Curve based key exchanges are not possible.
|
||||
// (Note that the group parameters must be specified separately)
|
||||
message DhPublicKey {
|
||||
// Big-endian two's complement encoded group element
|
||||
required bytes y = 1;
|
||||
}
|
||||
|
||||
message GenericPublicKey {
|
||||
required PublicKeyType type = 1;
|
||||
optional EcP256PublicKey ec_p256_public_key = 2;
|
||||
optional SimpleRsaPublicKey rsa2048_public_key = 3;
|
||||
// Use only as a last resort
|
||||
optional DhPublicKey dh2048_public_key = 4;
|
||||
}
|
||||
105
NearDrop/ProtobufSource/ukey.proto
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package securegcm;
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.security.cryptauth.lib.securegcm";
|
||||
option java_outer_classname = "UkeyProto";
|
||||
|
||||
message Ukey2Message {
|
||||
enum Type {
|
||||
UNKNOWN_DO_NOT_USE = 0;
|
||||
ALERT = 1;
|
||||
CLIENT_INIT = 2;
|
||||
SERVER_INIT = 3;
|
||||
CLIENT_FINISH = 4;
|
||||
}
|
||||
|
||||
optional Type message_type = 1; // Identifies message type
|
||||
optional bytes message_data = 2; // Actual message, to be parsed according to
|
||||
// message_type
|
||||
}
|
||||
|
||||
message Ukey2Alert {
|
||||
enum AlertType {
|
||||
// Framing errors
|
||||
BAD_MESSAGE = 1; // The message could not be deserialized
|
||||
BAD_MESSAGE_TYPE = 2; // message_type has an undefined value
|
||||
INCORRECT_MESSAGE = 3; // message_type received does not correspond to
|
||||
// expected type at this stage of the protocol
|
||||
BAD_MESSAGE_DATA = 4; // Could not deserialize message_data as per
|
||||
// value inmessage_type
|
||||
|
||||
// ClientInit and ServerInit errors
|
||||
BAD_VERSION = 100; // version is invalid; server cannot find
|
||||
// suitable version to speak with client.
|
||||
BAD_RANDOM = 101; // Random data is missing or of incorrect
|
||||
// length
|
||||
BAD_HANDSHAKE_CIPHER = 102; // No suitable handshake ciphers were found
|
||||
BAD_NEXT_PROTOCOL = 103; // The next protocol is missing, unknown, or
|
||||
// unsupported
|
||||
BAD_PUBLIC_KEY = 104; // The public key could not be parsed
|
||||
|
||||
// Other errors
|
||||
INTERNAL_ERROR = 200; // An internal error has occurred. error_message
|
||||
// may contain additional details for logging
|
||||
// and debugging.
|
||||
}
|
||||
|
||||
optional AlertType type = 1;
|
||||
optional string error_message = 2;
|
||||
}
|
||||
|
||||
enum Ukey2HandshakeCipher {
|
||||
RESERVED = 0;
|
||||
P256_SHA512 = 100; // NIST P-256 used for ECDH, SHA512 used for
|
||||
// commitment
|
||||
CURVE25519_SHA512 = 200; // Curve 25519 used for ECDH, SHA512 used for
|
||||
// commitment
|
||||
}
|
||||
|
||||
message Ukey2ClientInit {
|
||||
optional int32 version = 1; // highest supported version for rollback
|
||||
// protection
|
||||
optional bytes random = 2; // random bytes for replay/reuse protection
|
||||
|
||||
// One commitment (hash of ClientFinished containing public key) per supported
|
||||
// cipher
|
||||
message CipherCommitment {
|
||||
optional Ukey2HandshakeCipher handshake_cipher = 1;
|
||||
optional bytes commitment = 2;
|
||||
}
|
||||
repeated CipherCommitment cipher_commitments = 3;
|
||||
|
||||
// Next protocol that the client wants to speak.
|
||||
optional string next_protocol = 4;
|
||||
}
|
||||
|
||||
message Ukey2ServerInit {
|
||||
optional int32 version = 1; // highest supported version for rollback
|
||||
// protection
|
||||
optional bytes random = 2; // random bytes for replay/reuse protection
|
||||
|
||||
// Selected Cipher and corresponding public key
|
||||
optional Ukey2HandshakeCipher handshake_cipher = 3;
|
||||
optional bytes public_key = 4;
|
||||
}
|
||||
|
||||
message Ukey2ClientFinished {
|
||||
optional bytes public_key = 1; // public key matching selected handshake
|
||||
// cipher
|
||||
}
|
||||
236
NearDrop/ProtobufSource/wire_format.proto
Normal file
@@ -0,0 +1,236 @@
|
||||
// Copyright 2020 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Brought from: //depot/google3/location/nearby/sharing/proto/wire_format.proto
|
||||
// At CL 317565061
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package sharing.nearby;
|
||||
|
||||
// Required in Chrome.
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
// File metadata. Does not include the actual bytes of the file.
|
||||
// NEXT_ID=6
|
||||
message FileMetadata {
|
||||
enum Type {
|
||||
UNKNOWN = 0;
|
||||
IMAGE = 1;
|
||||
VIDEO = 2;
|
||||
APP = 3;
|
||||
AUDIO = 4;
|
||||
}
|
||||
|
||||
// The human readable name of this file (eg. 'Cookbook.pdf').
|
||||
optional string name = 1;
|
||||
|
||||
// The type of file (eg. 'IMAGE' from 'dog.jpg'). Specifying a type helps
|
||||
// provide a richer experience on the receiving side.
|
||||
optional Type type = 2 [default = UNKNOWN];
|
||||
|
||||
// The FILE payload id that will be sent as a follow up containing the actual
|
||||
// bytes of the file.
|
||||
optional int64 payload_id = 3;
|
||||
|
||||
// The total size of the file.
|
||||
optional int64 size = 4;
|
||||
|
||||
// The mimeType of file (eg. 'image/jpeg' from 'dog.jpg'). Specifying a
|
||||
// mimeType helps provide a richer experience on receiving side.
|
||||
optional string mime_type = 5 [default = "application/octet-stream"];
|
||||
|
||||
// A uuid for the attachment. Should be unique across all attachments.
|
||||
optional int64 id = 6;
|
||||
}
|
||||
|
||||
// NEXT_ID=5
|
||||
message TextMetadata {
|
||||
enum Type {
|
||||
UNKNOWN = 0;
|
||||
TEXT = 1;
|
||||
// Open with browsers.
|
||||
URL = 2;
|
||||
// Open with map apps.
|
||||
ADDRESS = 3;
|
||||
// Dial.
|
||||
PHONE_NUMBER = 4;
|
||||
}
|
||||
|
||||
// The title of the text content.
|
||||
optional string text_title = 2;
|
||||
|
||||
// The type of text (phone number, url, address, or plain text).
|
||||
optional Type type = 3 [default = UNKNOWN];
|
||||
|
||||
// The BYTE payload id that will be sent as a follow up containing the actual
|
||||
// bytes of the text.
|
||||
optional int64 payload_id = 4;
|
||||
|
||||
// The size of the text content.
|
||||
optional int64 size = 5;
|
||||
|
||||
// A uuid for the attachment. Should be unique across all attachments.
|
||||
optional int64 id = 6;
|
||||
}
|
||||
|
||||
// NEXT_ID=5
|
||||
message WifiCredentialsMetadata {
|
||||
enum SecurityType {
|
||||
UNKNOWN_SECURITY_TYPE = 0;
|
||||
OPEN = 1;
|
||||
WPA_PSK = 2;
|
||||
WEP = 3;
|
||||
}
|
||||
|
||||
// The Wifi network name. This will be sent in introduction.
|
||||
optional string ssid = 2;
|
||||
|
||||
// The security type of network (OPEN, WPA_PSK, WEP).
|
||||
optional SecurityType security_type = 3 [default = UNKNOWN_SECURITY_TYPE];
|
||||
|
||||
// The BYTE payload id that will be sent as a follow up containing the
|
||||
// password.
|
||||
optional int64 payload_id = 4;
|
||||
|
||||
// A uuid for the attachment. Should be unique across all attachments.
|
||||
optional int64 id = 5;
|
||||
}
|
||||
|
||||
// A frame used when sending messages over the wire.
|
||||
// NEXT_ID=3
|
||||
message Frame {
|
||||
enum Version {
|
||||
UNKNOWN_VERSION = 0;
|
||||
V1 = 1;
|
||||
}
|
||||
optional Version version = 1;
|
||||
|
||||
// Right now there's only 1 version, but if there are more, exactly one of
|
||||
// the following fields will be set.
|
||||
optional V1Frame v1 = 2;
|
||||
}
|
||||
|
||||
// NEXT_ID=7
|
||||
message V1Frame {
|
||||
enum FrameType {
|
||||
UNKNOWN_FRAME_TYPE = 0;
|
||||
INTRODUCTION = 1;
|
||||
RESPONSE = 2;
|
||||
PAIRED_KEY_ENCRYPTION = 3;
|
||||
PAIRED_KEY_RESULT = 4;
|
||||
CERTIFICATE_INFO = 5;
|
||||
CANCEL = 6;
|
||||
}
|
||||
|
||||
optional FrameType type = 1;
|
||||
|
||||
// Exactly one of the following fields will be set.
|
||||
optional IntroductionFrame introduction = 2;
|
||||
optional ConnectionResponseFrame connection_response = 3;
|
||||
optional PairedKeyEncryptionFrame paired_key_encryption = 4;
|
||||
optional PairedKeyResultFrame paired_key_result = 5;
|
||||
optional CertificateInfoFrame certificate_info = 6;
|
||||
}
|
||||
|
||||
// An introduction packet sent by the sending side. Contains a list of files
|
||||
// they'd like to share.
|
||||
// NEXT_ID=4
|
||||
message IntroductionFrame {
|
||||
repeated FileMetadata file_metadata = 1;
|
||||
repeated TextMetadata text_metadata = 2;
|
||||
// The required app package to open the content. May be null.
|
||||
optional string required_package = 3;
|
||||
repeated WifiCredentialsMetadata wifi_credentials_metadata = 4;
|
||||
}
|
||||
|
||||
// A response packet sent by the receiving side. Accepts or rejects the list of
|
||||
// files.
|
||||
// NEXT_ID=2
|
||||
message ConnectionResponseFrame {
|
||||
enum Status {
|
||||
UNKNOWN = 0;
|
||||
ACCEPT = 1;
|
||||
REJECT = 2;
|
||||
NOT_ENOUGH_SPACE = 3;
|
||||
UNSUPPORTED_ATTACHMENT_TYPE = 4;
|
||||
TIMED_OUT = 5;
|
||||
}
|
||||
|
||||
// The receiving side's response.
|
||||
optional Status status = 1;
|
||||
}
|
||||
|
||||
// A paired key encryption packet sent between devices, contains signed data.
|
||||
// NEXT_ID=3
|
||||
message PairedKeyEncryptionFrame {
|
||||
// The encrypted data in byte array format.
|
||||
optional bytes signed_data = 1;
|
||||
|
||||
// The hash of a certificate id.
|
||||
optional bytes secret_id_hash = 2;
|
||||
|
||||
// An optional encrypted data in byte array format.
|
||||
optional bytes optional_signed_data = 3;
|
||||
}
|
||||
|
||||
// A paired key verification result packet sent between devices.
|
||||
// NEXT_ID=2
|
||||
message PairedKeyResultFrame {
|
||||
enum Status {
|
||||
UNKNOWN = 0;
|
||||
SUCCESS = 1;
|
||||
FAIL = 2;
|
||||
UNABLE = 3;
|
||||
}
|
||||
|
||||
// The verification result.
|
||||
optional Status status = 1;
|
||||
}
|
||||
|
||||
// A package containing certificate info to be shared to remote device offline.
|
||||
// NEXT_ID=2
|
||||
message CertificateInfoFrame {
|
||||
// The public certificates to be shared with remote devices.
|
||||
repeated PublicCertificate public_certificate = 1;
|
||||
}
|
||||
|
||||
// A public certificate from the local device.
|
||||
// NEXT_ID=8
|
||||
message PublicCertificate {
|
||||
// The unique id of the public certificate.
|
||||
optional bytes secret_id = 1;
|
||||
|
||||
// A bytes representation of a Secret Key owned by contact, to decrypt the
|
||||
// metadata_key stored within the advertisement.
|
||||
optional bytes authenticity_key = 2;
|
||||
|
||||
// A bytes representation a public key of X509Certificate, owned by contact,
|
||||
// to decrypt encrypted UKEY2 (from Nearby Connections API) as a hand shake in
|
||||
// contact verification phase.
|
||||
optional bytes public_key = 3;
|
||||
|
||||
// The time in millis from epoch when this certificate becomes effective.
|
||||
optional int64 start_time = 4;
|
||||
|
||||
// The time in millis from epoch when this certificate expires.
|
||||
optional int64 end_time = 5;
|
||||
|
||||
// The encrypted metadata in bytes, contains personal information of the
|
||||
// device/user who created this certificate. Needs to be decrypted into bytes,
|
||||
// and converted back to EncryptedMetadata object to access fields.
|
||||
optional bytes encrypted_metadata_bytes = 6;
|
||||
|
||||
// The tag for verifying metadata_encryption_key.
|
||||
optional bytes metadata_encryption_key_tag = 7;
|
||||
}
|
||||
|
||||
// NEXT_ID=3
|
||||
message WifiCredentials {
|
||||
// Wi-Fi password.
|
||||
optional string password = 1;
|
||||
// True if the network is a hidden network that is not broadcasting its SSID.
|
||||
// Default is false.
|
||||
optional bool hidden_ssid = 2 [default = false];
|
||||
}
|
||||
BIN
NearDrop/ru.lproj/Localizable.strings
Normal file
26
NearDrop/ru.lproj/Localizable.stringsdict
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NFiles</key>
|
||||
<dict>
|
||||
<key>NSStringLocalizedFormatKey</key>
|
||||
<string>%#@files@</string>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>NSStringFormatSpecTypeKey</key>
|
||||
<string>NSStringPluralRuleType</string>
|
||||
<key>NSStringFormatValueTypeKey</key>
|
||||
<string>d</string>
|
||||
<key>one</key>
|
||||
<string>%d файл</string>
|
||||
<key>few</key>
|
||||
<string>%d файла</string>
|
||||
<key>many</key>
|
||||
<string>%d файлов</string>
|
||||
<key>other</key>
|
||||
<string>%d файлов</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
196
PROTOCOL.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# Google's Nearby Share protocol
|
||||
|
||||
This document describes the Nearby Share protocol as understood by me (@grishka) from Chromium sources (that are way too convoluted) and decompiled Google Services Framework apk (that, despite being a decompilation of obfuscated code, is still more helpful than Chromium sources).
|
||||
|
||||
The protocol is peer-to-peer, end-to-end encrypted. Overall, it appears like it was mostly designed to run over an unreliable medium like UDP, but I've only observed it over TCP.
|
||||
|
||||
Only the WiFi LAN protocol is described here because that's what I reverse engineered, but the data running over other mediums (Bluetooth, WiFi Direct, ...) is most probably largely the same.
|
||||
|
||||
If you want to build your own Nearby Share *thing*, you will need:
|
||||
|
||||
1. An implementation of multicast DNS (most modern OSes have it built-in)
|
||||
2. A cryptography library that is capable of ECDSA key exchange, AES-CBC, HMAC, and SHA256. OpenSSL will do but is definitely an overkill.
|
||||
3. A Protobuf library
|
||||
4. [These Protobuf files](/NearDrop/ProtobufSource) I collected from the Chromium sources so you don't have to
|
||||
|
||||
It is also very helpful to read logcat on your Android device if you're having any trouble. The logging of the Android implementation of Nearby Share is very verbose.
|
||||
|
||||
### Device roles
|
||||
|
||||
Since a file transfer is unidirectional, the peers are assigned roles:
|
||||
|
||||
* The receiving side is the **server**. It listens on a TCP port and advertises an MDNS service.
|
||||
* The sending side is the **client**. It discovers the MDNS service and connects to the server's TCP port.
|
||||
|
||||
### How devices find each other
|
||||
|
||||
To become visible in the sheet on Android devices, a *server* advertises an MDNS service. The **domain** is empty. The **type** is `_FC9F5ED42C8A._tcp.`. The **port** is an arbitrary TCP port on which the server accepts incoming connections.
|
||||
|
||||
The **name** is the following 10 bytes encoded in URL-safe base64:
|
||||
|
||||
* `0x23`, Google calls this "PCP" but I have no idea what it is
|
||||
* 4-byte **endpoint ID**
|
||||
* 3-byte **service ID**: `0xFC, 0x9F, 0x5E`
|
||||
* 2 zero bytes that serve an unknown purpose
|
||||
|
||||
The **endpoint ID** is 4 random alphanumeric characters. It identifies devices to each other. Android uses it in its logs quite extensively.
|
||||
|
||||
The service also needs to have a TXT record with key `n` and the value of the following encoded in URL-safe base64 ("endpoint info"):
|
||||
|
||||
* 1 byte: bit field
|
||||
* 3 bits: version, set to 0
|
||||
* 1 bit: visibility, 0 = visible
|
||||
* 3 bits: device type. Android uses this to pick an icon. 0 = unknown, 1 = phone, 2 = tablet, 3 = laptop
|
||||
* 1 bit: reserved, set to 0
|
||||
* 16 bytes of unknown purpose. I set them to random.
|
||||
* User-visible device name in UTF-8, prefixed with 1-byte length.
|
||||
|
||||
Android does not advertise the MDNS service all the time regardless of the visibility setting. It waits for some kind of signal to start it and also show the "A device nearby is sharing" notification. As of now, it is unknown what exactly is it that it's waiting for. Probably a broadcast packet of some kind over either WiFi or Bluetooth.
|
||||
|
||||
The service ID (FC9F...) comes from SHA256("NearbySharing") = `fc9f5ed42c8a5e9e94684076ef3bf938a809c60ad354992b0435aebbdc58b97b`.
|
||||
|
||||
### High-level diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
Client-->>Server: (Connects to advertised TCP port)
|
||||
Client->>Server: Connection request
|
||||
Client->>Server: UKEY2 ClientInit
|
||||
Server->>Client: UKEY2 ServerInit
|
||||
Client->>Server: UKEY2 ClientFinish
|
||||
Client->>Server: Connection response
|
||||
Note over Server, Client: All following packets are encrypted
|
||||
Server->>Client: Paired key encryption
|
||||
Client->>Server: Paired key encryption
|
||||
Server->>Client: Paired key result
|
||||
Client->>Server: Paired key result
|
||||
Client->>Server: Introduction (transfer metadata)
|
||||
Note over Server: Asks the user
|
||||
Server->>Client: Response (accept/reject)
|
||||
Client->>Server: File chunks
|
||||
Client-->>Server:
|
||||
Client-->>Server:
|
||||
Client->>Server: Disconnection
|
||||
Client-->Server: (Close TCP connection)
|
||||
```
|
||||
|
||||
From the Google point of view, the "Nearby connections" part is a separate universal transport layer, over which the "Share" runs. This may explain some bizarre arrangements where you have protobuf inside protobuf inside encrypted protobuf inside protobuf.
|
||||
|
||||
### Frame/packet/message types
|
||||
|
||||
There are three types of packets that can appear directly ~~on the wire~~ in the air:
|
||||
|
||||
1. **Offline frames.** These are the basic uint of the nearby protocol. They are used to control the connection.
|
||||
2. **UKEY2 messages.** These are used for the encryption key exchange (UKEY2 is Google's bespoke algorithm for that).
|
||||
3. **Secure messages.** These are used exclusively after the initial negotiation and carry other packets inside them in the encrypted form.
|
||||
|
||||
Keep the protobuf files open to follow along.
|
||||
|
||||
### TCP framing
|
||||
|
||||
Each protobuf message sent over the TCP connection is prefixed with 4-byte big-endian (MSB first) length.
|
||||
|
||||
### Initial handshake & key exchange
|
||||
|
||||
(described from the server/recipient point of view)
|
||||
|
||||
After the client connects to the server, it sends two packets: a "connection request" and a "UKEY2 client init".
|
||||
|
||||
#### Connection request
|
||||
|
||||
This is a subtype of "offline frame".
|
||||
The client wants to connect to the server and tells it about itself. The only field of interest here is `endpointInfo`. It contains the device type and name. It has the same format as the `n` TXT record described above, just without the base64 encoding.
|
||||
|
||||
#### UKEY2 client init
|
||||
|
||||
This is a subtype of "UKEY2 message". Google's UKEY2 reference implementation [is open source](https://github.com/google/ukey2) and comes with documentation. Please refer to that repo for details on the key exchange.
|
||||
This is the initial step of the key exchange for end-to-end encryption. Upon receiving this, the server generates a ECDSA key pair and sends its public key in a "server init". The server also needs to remember the raw serialized client init message for the final key derivation step. The outgoing server init message is also needed for the next step. The bytes include the entire protobuf message but do not include the int32 length prefix.
|
||||
|
||||
After receiving the server init, the client completes the key derivation and sends a "client finish", containing its public key.
|
||||
|
||||
#### UKEY2 client finish
|
||||
|
||||
This is where the server completes the key derivation. This step is described in detail [in the Google readme](https://github.com/google/ukey2#deriving-the-authentication-string-and-the-next-protocol-secret).
|
||||
|
||||
The result of the key exchange is two values: the authentication string and the next protocol secret.
|
||||
|
||||
The **next protocol secret** is further processed to obtain the two 32-byte AES and two 32-byte HMAC keys used for encryption and authentication of further communications ([relevant Chromium code](https://source.chromium.org/chromium/chromium/src/+/main:third_party/securemessage/src/cpp/src/securemessage/crypto_ops.cc) and [this as well](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/ukey2/src/src/main/cpp/src/securegcm/d2d_crypto_ops.cc)):
|
||||
|
||||
Derive two 32-byte "device to device" keys using HKDF-SHA256:
|
||||
|
||||
* **D2D client key**, using the **next protocol secret** for input key material, `82AA55A0D397F88346CA1CEE8D3909B95F13FA7DEB1D4AB38376B8256DA85510` for salt, and the string `client` for info
|
||||
* **D2D cerver key**, using the same parameters, except **info** is `server`
|
||||
|
||||
Next, derive the four keys you will use for the actual encryption. All four use the same value of salt, which is `SHA256("SecureMessage")`, or `BF9D2A53C63616D75DB0A7165B91C1EF73E537F2427405FA23610A4BE657642E`. These keys are from the server POV; if you're the client, they need to be swapped around (decrypt/receive shoud use the server key and vice versa).
|
||||
|
||||
* **Decrypt key**: IKM = D2D client key, info = `ENC:2`
|
||||
* **Receive HMAC key**: IKM = D2D client key, info = `SIG:1`
|
||||
* **Encrypt key**: IKM = D2D server key, info = `ENC:2`
|
||||
* **Send HMAC key**: IKM = D2D server key, info = `SIG:1`
|
||||
|
||||
The key exchange is now complete.
|
||||
|
||||
The **authentication string** is used for out-of-band key verification. Nearby Share doesn't use the algorithm specified by UKEY2. Instead, a 4-digit PIN code is generated using [this algorithm](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc;l=215-230;drc=9468ba955b5794fdfaa7301fce4fb70940830c88).
|
||||
|
||||
#### Connection response
|
||||
|
||||
After the key exchange is complete, the client sends one last plaintext message to the server: a connection response. It's a subtype of offline frame saying that the client has accepted the connection (the connection it itself initiated... whatever). All the following communication is encrypted and wrapped in the payload layer.
|
||||
|
||||
### The encryption layer
|
||||
|
||||
The message type on the wire is always the "secure message". A secure message has two fields: header and body, and the signature.
|
||||
|
||||
Header and body is a serialized `HeaderAndBody` message. Inside, there are two fields, that are (what a surprise!) header and body. The body contains the encrypted payload. The header contains the encryption scheme (must be set to `AES256_CBC`), the signature scheme (must be set to `HMAC_SHA256`), the IV (initialization vector) for AES-CBC consisting of 16 random bytes, and the public metadata. Public metadata is needed because the protocol is extensible af. It contains two fields with constant values: version that is always 1 and type that is always `DEVICE_TO_DEVICE_MESSAGE`.
|
||||
|
||||
The signature is a HMAC-SHA256 of the header-and-body fields using one of the keys derived above.
|
||||
|
||||
The body inside header-and-body is encrypted using AES-CBC with PKCS7 padding. After decryption it should be a valid device to device message (see securegcm.proto). If it isn't, you did something wrong. Go back and debug your key exchange code. Cryptography is messy, don't worry, no one gets it right on the first try ¯\\\_(ツ)_/¯
|
||||
|
||||
The device to device message contains a sequence number and a message. The message is always a serialized offline frame. The sequence number starts at 0 and is incremented with each message. Client and server have their own independent sequence numbers.
|
||||
|
||||
### The payload layer
|
||||
|
||||

|
||||
|
||||
This layer allows the transfer of arbitrarily large payloads in chunks. Payloads come in two types: bytes and files. All negotiation uses bytes payloads with protobuf messages inside. The file payloads are used for actual files.
|
||||
|
||||
Payload transfer frames are wrapped into offline frames of type `PAYLOAD_TRANSFER`. These are then encrypted as described above. Meaning of the important payload transfer frame fields is as follows:
|
||||
|
||||
* **header**: the metadata
|
||||
* **id**: the payload identifier within the connection. Allows transferring multiple payloads in parallel. You use it to keep track of multiple transfers, associate buffers and files to it, etc.
|
||||
* **type**: either `BYTES` or `FILE`
|
||||
* **totalSize**: self-explanatory
|
||||
* **chunk**: the data itself
|
||||
* **offset**: the offset at which this chunk needs to be written into the buffer or file
|
||||
* **flags**: if `LAST_CHUNK` (bit 0) is set, the transfer is complete and this is the last chunk
|
||||
* **body**: the data bytes themselves
|
||||
|
||||
Android does this thing where it sends 2 payload transfer frames in succession for each negotiation message: the first contains the entire message, the second contains 0 bytes but has the `LAST_CHUNK` flag set. I replicated this behavior in NearDrop.
|
||||
|
||||
### The "paired key encryption", whatever that is
|
||||
|
||||
The client and the server send each other a "paired key encryption" frame, wrapped into the payload layer. *Presumably*, this is used for all the visibility-restriction phone number stuff. Also presumably getting the data contained within involves talking to Google servers. I set `secretIDHash` to 6 random bytes and `signedData` to 72 random bytes in the ones I send. It works fine.
|
||||
|
||||
After that, the client and the server send each other a "paired key result" frame. Both have `status` set to `UNABLE`. Whatever.
|
||||
|
||||
These and following protobuf messages are specific to Nearby Share and [are defined here](/NearDrop/ProtobufSource/wire_format.proto).
|
||||
|
||||
### The transfer metadata aka introduction
|
||||
|
||||
After the successful exchange of the meaningless paired key encryption frames, the client sends an "introduction" frame to the server. This contains the list of files that the client is about to send to the server. The fields should be self-explanatory. The `payload_id` will be used in the payload layer for transferring that particluar file.
|
||||
|
||||
At this point, Android shows that the connection was successful and displays the PIN code. The server would prompt the user to accept the transfer.
|
||||
|
||||
### The file transfer
|
||||
|
||||
#### Accepting the transfer
|
||||
|
||||
To accept the transfer, the server sends a "response" frame with `status` set to `ACCEPT`. The client will then start sending file chunks over the payload layer. You did it 🎉
|
||||
|
||||
#### Rejecting the transfer
|
||||
|
||||
Do the same but set `status` to `REJECT`. There are also other status codes, like `NOT_ENOUGH_SPACE`, that result in Android showing a different error.
|
||||
|
||||
### Keep-alive frames
|
||||
|
||||
Android sends offline frames of type `KEEP_ALIVE` every 10 seconds and expects the server to do the same. If you don't, it will terminate the connection after a while thinking your app crashed or something. This especially comes into play when sending large files. No, TCP's built-in acknowledgements are not enough. There are so many abstraction layers that whoever came up with this forgot about them.
|
||||
28
README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
**NearDrop** is a partial implementation of [Google's Nearby Share](https://blog.google/products/android/nearby-share/) for macOS.
|
||||
|
||||
[Protocol documentation](/PROTOCOL.md) is available separately.
|
||||
|
||||
The app lives in your menu bar and saves files to your downloads folder. It's that simple, really.
|
||||
|
||||
## Limitations
|
||||
|
||||
* **Receive only**. For now. I haven't yet figured out how to make Android turn on the MDNS service and/or show the "a device nearby is sharing" notification.
|
||||
* **Wi-Fi LAN only**. Your Android device and your Mac need to be on the same network for this app to work. Google's implementation supports multiple mediums, including Wi-Fi Direct, Wi-Fi hotspot, Bluetooth, some kind of 5G peer-to-peer connection, and even a WebRTC-based protocol that goes over the internet through Google servers. Wi-Fi direct isn't supported on macOS (Apple has their own, incompatible, AWDL thing, used in AirDrop). Bluetooth needs further reverse engineering.
|
||||
|
||||
## Installation
|
||||
|
||||
Download the latest build from the releases section, unzip, move to your applications folder. Do the usual Gatekeeper thing to run an Apple-untrusted app for the first time. If you want the app to start on boot, add it manually to login objects in System Preferences.
|
||||
|
||||
## FAQ
|
||||
|
||||
#### Why is the app not notarized?
|
||||
|
||||
Because I don't want to pay Apple $99 a year for the privilege of developing macOS apps and oppose their idea of security.
|
||||
|
||||
#### Why is this not on the app store?
|
||||
|
||||
Because I don't want to pay Apple $99 a year for the privilege of developing macOS apps. I also don't want to have to go through the review process.
|
||||
|
||||
#### Why not the other way around, i.e. AirDrop on Android?
|
||||
|
||||
While I am an Android developer, and I have looked into this, this is nigh-impossible. AirDrop uses [AWDL](https://stackoverflow.com/questions/19587701/what-is-awdl-apple-wireless-direct-link-and-how-does-it-work), Apple's own proprietary take on peer-to-peer Wi-Fi. This works on top of 802.11 itself, the low-level Wi-Fi protocol, and thus can not be implemented without messing around with the Wi-Fi adapter drivers and raw packets and all that. It might be possible on Android, but it would at the very least require root and possibly a custom kernel. There is [an open-source implementation of AWDL and AirDrop for Linux](https://owlink.org/code/).
|
||||
BIN
images/YoDawg.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |