use of swift-crypto for linux, passwords hashed with SHA512, NSImage for macOS only
parent
e0137f3948
commit
70ea2934f0
|
@ -0,0 +1,105 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1240"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BandikaSwiftBase_BandikaSwiftBase"
|
||||
BuildableName = "BandikaSwiftBase_BandikaSwiftBase"
|
||||
BlueprintName = "BandikaSwiftBase_BandikaSwiftBase"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BandikaSwiftBase"
|
||||
BuildableName = "BandikaSwiftBase"
|
||||
BlueprintName = "BandikaSwiftBase"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BandikaSwiftBaseTests"
|
||||
BuildableName = "BandikaSwiftBaseTests"
|
||||
BlueprintName = "BandikaSwiftBaseTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BandikaSwiftBaseTests"
|
||||
BuildableName = "BandikaSwiftBaseTests"
|
||||
BlueprintName = "BandikaSwiftBaseTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</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">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "BandikaSwiftBase_BandikaSwiftBase"
|
||||
BuildableName = "BandikaSwiftBase_BandikaSwiftBase"
|
||||
BlueprintName = "BandikaSwiftBase_BandikaSwiftBase"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -1,6 +1,15 @@
|
|||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "swift-crypto",
|
||||
"repositoryURL": "https://github.com/apple/swift-crypto",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "3bea268b223651c4ab7b7b9ad62ef9b2d4143eb6",
|
||||
"version": "1.1.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "swift-nio",
|
||||
"repositoryURL": "https://github.com/apple/swift-nio",
|
||||
|
@ -24,8 +33,8 @@
|
|||
"repositoryURL": "https://github.com/mr-elbe5/SwiftyHttpServer",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "4fda28adcc5999aa018f91796b19bb92b22adcd5",
|
||||
"version": "1.1.12"
|
||||
"revision": "7e809798b9bdfed52501c0180a17206c87749c1c",
|
||||
"version": "1.1.13"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -13,7 +13,8 @@ let package = Package(
|
|||
targets: ["BandikaSwiftBase"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/mr-elbe5/SwiftyHttpServer", from: "1.1.12"),
|
||||
.package(url: "https://github.com/mr-elbe5/SwiftyHttpServer", from: "1.1.13"),
|
||||
.package(url: "https://github.com/apple/swift-crypto", from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
|
@ -21,7 +22,8 @@ let package = Package(
|
|||
.target(
|
||||
name: "BandikaSwiftBase",
|
||||
dependencies: [
|
||||
"SwiftyHttpServer"
|
||||
"SwiftyHttpServer",
|
||||
.product(name: "Crypto", package: "swift-crypto")
|
||||
],
|
||||
resources: [
|
||||
.copy("Resources")
|
||||
|
|
|
@ -31,7 +31,9 @@ public class ActionQueue{
|
|||
if timer == nil{
|
||||
stop()
|
||||
}
|
||||
timer = Timer.scheduledTimer(timeInterval: 30.0, target: self, selector: #selector(checkActions), userInfo: nil, repeats: true)
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 30.0, repeats: true) { timer in
|
||||
self.checkActions()
|
||||
}
|
||||
}
|
||||
|
||||
public func stop(){
|
||||
|
@ -49,7 +51,7 @@ public class ActionQueue{
|
|||
}
|
||||
}
|
||||
|
||||
@objc public func checkActions() {
|
||||
public func checkActions() {
|
||||
lock()
|
||||
defer{unlock()}
|
||||
for action in regularActions{
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import Cocoa
|
||||
|
||||
extension NSImage {
|
||||
|
@ -40,3 +41,5 @@ extension NSImage {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -79,7 +79,7 @@ public class Statics: Codable{
|
|||
|
||||
public func initDefaults(){
|
||||
salt = Statics.generateSaltString()
|
||||
defaultPassword = UserSecurity.encryptPassword(password: "pass", salt: salt)
|
||||
defaultPassword = UserSecurity.encryptPassword(password: "pass")
|
||||
defaultLocale = Locale(identifier: "en")
|
||||
shutdownCode = Statics.generateShutdownCode()
|
||||
}
|
||||
|
@ -94,27 +94,14 @@ public class Statics: Codable{
|
|||
return true
|
||||
}
|
||||
|
||||
private static func generateSalt() -> [UInt8] {
|
||||
var bytes = [UInt8](repeating: 0, count: 8)
|
||||
_ = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
|
||||
return bytes
|
||||
}
|
||||
|
||||
private static func generateSaltString() -> String {
|
||||
let salt = Data(bytes: generateSalt(), count: 8).base64EncodedString()
|
||||
let salt = String.generateRandomString(length: 8)
|
||||
Log.debug("generated salt string '\(salt)'")
|
||||
return salt
|
||||
}
|
||||
|
||||
private static func generateShutdownCode() -> String {
|
||||
var bytes = [UInt8](repeating: 0, count: 8)
|
||||
_ = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
|
||||
var code = Data(bytes: bytes, count: 8).base64EncodedString()
|
||||
// replace leading "/" as it destroys valid shutdown url
|
||||
if code.hasPrefix("/"){
|
||||
code.remove(at: code.startIndex)
|
||||
code = "#" + code
|
||||
}
|
||||
let code = String.generateRandomString(length: 8)
|
||||
Log.debug("generated shutdown code '\(code)'")
|
||||
return code
|
||||
}
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import Cocoa
|
||||
import SwiftyHttpServer
|
||||
|
||||
#if os(macOS)
|
||||
import Cocoa
|
||||
#endif
|
||||
|
||||
extension MemoryFile{
|
||||
|
||||
public func createPreview(fileName: String, maxSize: Int) -> MemoryFile?{
|
||||
#if os(macOS)
|
||||
if let src = NSImage(data: data){
|
||||
if let previewImage : NSImage = src.resizeMaintainingAspectRatio(withSize: NSSize(width: FileData.MAX_PREVIEW_SIDE, height: FileData.MAX_PREVIEW_SIDE)){
|
||||
if let tiff = previewImage.tiffRepresentation, let tiffData = NSBitmapImageRep(data: tiff) {
|
||||
|
@ -21,6 +25,9 @@ extension MemoryFile{
|
|||
}
|
||||
}
|
||||
return nil
|
||||
#else
|
||||
return nil
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,8 +175,7 @@ public class UserContainer : DataContainer{
|
|||
|
||||
public func getUser(login: String, pwd: String) -> UserData?{
|
||||
if let data = userLoginMap[login]{
|
||||
let passwordHash : String = UserSecurity.encryptPassword(password: pwd, salt: Statics.instance.salt)
|
||||
if data.passwordHash == passwordHash {
|
||||
if UserSecurity.verifyPassword(savedHash: data.passwordHash, password: pwd){
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ public class UserData: BaseData {
|
|||
if password.isEmpty {
|
||||
passwordHash = ""
|
||||
} else {
|
||||
passwordHash = UserSecurity.encryptPassword(password: password, salt: Statics.instance.salt)
|
||||
passwordHash = UserSecurity.encryptPassword(password: password)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,35 @@
|
|||
*/
|
||||
|
||||
import Foundation
|
||||
import SwiftyLog
|
||||
#if os(macOS)
|
||||
// not available on linux, so no PBKDF2
|
||||
import CommonCrypto
|
||||
#endif
|
||||
import Crypto
|
||||
|
||||
public class UserSecurity{
|
||||
|
||||
private static var rounds : UInt32 = 2205
|
||||
private static var keyByteCount : Int = 160
|
||||
|
||||
public static func verifyPassword(savedHash: String, password: String) -> Bool{
|
||||
var passwordHash : String = encryptPassword(password: password)
|
||||
if savedHash == passwordHash {
|
||||
return true
|
||||
}
|
||||
//backward compatibility
|
||||
#if os(macOS)
|
||||
passwordHash = encryptPassword(password: password, salt: Statics.instance.salt)
|
||||
if savedHash == passwordHash {
|
||||
return true
|
||||
}
|
||||
#endif
|
||||
return false
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
// not available on linux, so no PBKDF2
|
||||
public static func encryptPassword(password : String, salt: String) -> String{
|
||||
var outputBytes = Array<UInt8>(repeating: 0, count: kCCKeySizeAES256)
|
||||
let status = CCKeyDerivationPBKDF(
|
||||
|
@ -32,5 +54,17 @@ public class UserSecurity{
|
|||
}
|
||||
return Data(outputBytes).base64EncodedString()
|
||||
}
|
||||
#endif
|
||||
|
||||
public static func encryptPassword(password : String) -> String{
|
||||
let inputData = Data(password.utf8)
|
||||
let hashed = SHA512.hash(data: inputData)
|
||||
let hashString = hashed.compactMap{
|
||||
String(format: "%02x", $0)
|
||||
}.joined()
|
||||
Log.debug("password hash = \(hashString)")
|
||||
return hashString
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue