mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-22 16:29:23 +00:00
Password creator nor correctly supports composed characters.
This mainly enabeld Emoji support
This commit is contained in:
18
MacPass/NSString+MPComposedCharacterAdditions.h
Normal file
18
MacPass/NSString+MPComposedCharacterAdditions.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// NSString+MPComposedCharacterLength.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 03.05.17.
|
||||
// Copyright © 2017 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSString (MPComposedCharacterAdditions)
|
||||
|
||||
@property (nonatomic, readonly) NSUInteger composedCharacterLength;
|
||||
@property (nonatomic, readonly, copy) NSArray<NSValue *> *composedCharacterRanges; // NSArray of NSValues of NSRanges
|
||||
|
||||
- (NSString *)composedCharacterAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
39
MacPass/NSString+MPComposedCharacterAdditions.m
Normal file
39
MacPass/NSString+MPComposedCharacterAdditions.m
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// NSString+MPComposedCharacterLength.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 03.05.17.
|
||||
// Copyright © 2017 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSString+MPComposedCharacterAdditions.h"
|
||||
|
||||
@implementation NSString (MPComposedCharacterAdditions)
|
||||
|
||||
- (NSUInteger)composedCharacterLength {
|
||||
NSUInteger __block actualLength = 0;
|
||||
[self enumerateSubstringsInRange:NSMakeRange(0, self.length)
|
||||
options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
|
||||
actualLength++;
|
||||
}];
|
||||
return actualLength;
|
||||
}
|
||||
|
||||
- (NSArray<NSValue *> *)composedCharacterRanges {
|
||||
__block NSMutableArray *ranges = [[NSMutableArray alloc] initWithCapacity:self.length];
|
||||
[self enumerateSubstringsInRange:NSMakeRange(0, self.length)
|
||||
options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
|
||||
[ranges addObject:[NSValue valueWithRange:substringRange]];
|
||||
}];
|
||||
return [ranges copy];
|
||||
}
|
||||
|
||||
- (NSString *)composedCharacterAtIndex:(NSUInteger)index {
|
||||
NSArray <NSValue *> *ranges = self.composedCharacterRanges;
|
||||
if(index < ranges.count) {
|
||||
return [self substringWithRange:ranges[index].rangeValue];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -40,6 +40,12 @@ typedef NS_OPTIONS(NSUInteger, MPPasswordCharacterFlags) {
|
||||
+ (NSString *)passwordFromString:(NSString *)source length:(NSUInteger)length;
|
||||
|
||||
+ (NSString *)passwordWithDefaultSettings;
|
||||
|
||||
/**
|
||||
* @return returns a random character from the string
|
||||
*/
|
||||
@property (nonatomic, readonly, copy) NSString *randomCharacter;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates a random password with only the characters of the receiver
|
||||
@@ -49,10 +55,6 @@ typedef NS_OPTIONS(NSUInteger, MPPasswordCharacterFlags) {
|
||||
* @return Password containing only the characters in receiver
|
||||
*/
|
||||
- (NSString *)passwordWithLength:(NSUInteger)length;
|
||||
/**
|
||||
* @return returns a random character from the string
|
||||
*/
|
||||
- (NSString *)randomCharacter;
|
||||
/**
|
||||
* Calculates the entropy of the receiver based on the allowed characters. The calculation considers the characters chosen randomly.
|
||||
* If the password supplied was not created randomly based on the full character set, the calculated entropy is NOT correct.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#import "NSString+MPPasswordCreation.h"
|
||||
#import "KeePassKit/KeePassKit.h"
|
||||
|
||||
#import "NSString+MPComposedCharacterAdditions.h"
|
||||
#import "MPSettingsHelper.h"
|
||||
|
||||
NSString *const kMPLowercaseLetterCharacters = @"abcdefghijklmnopqrstuvwxyz";
|
||||
@@ -33,8 +34,7 @@ static NSString *allowedCharactersString(MPPasswordCharacterFlags flags) {
|
||||
}
|
||||
|
||||
static NSString *mergeWithoutDuplicates(NSString* baseCharacters, NSString* customCharacters){
|
||||
NSInteger maxLength = baseCharacters.length + customCharacters.length;
|
||||
NSMutableString* mergedCharacters = [NSMutableString stringWithCapacity: maxLength];
|
||||
NSMutableString* mergedCharacters = [[NSMutableString alloc] init];
|
||||
[mergedCharacters appendString:baseCharacters];
|
||||
[customCharacters enumerateSubstringsInRange: NSMakeRange(0, customCharacters.length)
|
||||
options: NSStringEnumerationByComposedCharacterSequences
|
||||
@@ -50,7 +50,7 @@ static NSString *mergeWithoutDuplicates(NSString* baseCharacters, NSString* cust
|
||||
|
||||
+ (NSString *)passwordFromString:(NSString *)source length:(NSUInteger)length {
|
||||
NSMutableString *password = [[NSMutableString alloc] initWithCapacity:length];
|
||||
while(password.length < length) {
|
||||
while(password.composedCharacterLength < length) {
|
||||
[password appendString:[source randomCharacter]];
|
||||
}
|
||||
return password;
|
||||
@@ -63,7 +63,7 @@ static NSString *mergeWithoutDuplicates(NSString* baseCharacters, NSString* cust
|
||||
NSString *characters = mergeWithoutDuplicates(
|
||||
allowedCharactersString(allowedCharacters),
|
||||
customCharacters);
|
||||
while(password.length < length) {
|
||||
while(password.composedCharacterLength < length) {
|
||||
NSString *randomCharacter = [characters randomCharacter];
|
||||
if(randomCharacter.length > 0) {
|
||||
[password appendString:randomCharacter];
|
||||
@@ -77,10 +77,10 @@ static NSString *mergeWithoutDuplicates(NSString* baseCharacters, NSString* cust
|
||||
|
||||
+ (NSString *)passwordWithDefaultSettings {
|
||||
/* generate and pre-fill password using default password creation settings */
|
||||
NSUInteger passwordLength = [[NSUserDefaults standardUserDefaults] integerForKey:kMPSettingsKeyDefaultPasswordLength];
|
||||
MPPasswordCharacterFlags characterFlags = [[NSUserDefaults standardUserDefaults] integerForKey:kMPSettingsKeyPasswordCharacterFlags];
|
||||
BOOL useCustomString = [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyPasswordUseCustomString];
|
||||
NSString *customString = [[NSUserDefaults standardUserDefaults] stringForKey:kMPSettingsKeyPasswordCustomString];
|
||||
NSUInteger passwordLength = [NSUserDefaults.standardUserDefaults integerForKey:kMPSettingsKeyDefaultPasswordLength];
|
||||
MPPasswordCharacterFlags characterFlags = [NSUserDefaults.standardUserDefaults integerForKey:kMPSettingsKeyPasswordCharacterFlags];
|
||||
BOOL useCustomString = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyPasswordUseCustomString];
|
||||
NSString *customString = [NSUserDefaults.standardUserDefaults stringForKey:kMPSettingsKeyPasswordCustomString];
|
||||
|
||||
if(useCustomString && customString.length > 0) {
|
||||
return [customString passwordWithLength:passwordLength];
|
||||
@@ -95,27 +95,25 @@ static NSString *mergeWithoutDuplicates(NSString* baseCharacters, NSString* cust
|
||||
}
|
||||
|
||||
- (NSString *)randomCharacter {
|
||||
if([self length] == 0) {
|
||||
if(self.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
NSData *data = [NSData kpk_dataWithRandomBytes:sizeof(NSUInteger)];
|
||||
NSUInteger randomIndex;
|
||||
[data getBytes:&randomIndex length:data.length];
|
||||
return [self substringWithRange:NSMakeRange(randomIndex % self.length, 1)];
|
||||
return [self composedCharacterAtIndex:(randomIndex % self.composedCharacterLength)];
|
||||
}
|
||||
|
||||
- (CGFloat)entropyWhithPossibleCharacterSet:(MPPasswordCharacterFlags)allowedCharacters orCustomCharacters:(NSString *)customCharacters {
|
||||
NSString *characters = nil;
|
||||
if([[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyPasswordUseCustomString] && nil != customCharacters) {
|
||||
characters = mergeWithoutDuplicates(
|
||||
allowedCharactersString(allowedCharacters),
|
||||
customCharacters);
|
||||
if([NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyPasswordUseCustomString] && nil != customCharacters) {
|
||||
characters = mergeWithoutDuplicates(allowedCharactersString(allowedCharacters), customCharacters);
|
||||
}
|
||||
else {
|
||||
characters = allowedCharactersString(allowedCharacters);
|
||||
}
|
||||
CGFloat alphabetCount = characters.length;
|
||||
CGFloat passwordLength = self.length;
|
||||
CGFloat alphabetCount = characters.composedCharacterLength;
|
||||
CGFloat passwordLength = self.composedCharacterLength;
|
||||
return passwordLength * ( log10(alphabetCount) / log10(2) );
|
||||
}
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user