importFoundationimportSecurityimportDarwinimportCommonCrypto//Unsafebindingstolibcsrandandrand@_silgen_name("srand")funcc_srand(_seed:UInt32)@_silgen_name("rand")funcc_rand()->Int32structMastgTest{//Insecure:libcrandseededwithtime,predictableandnotsuitableforcryptographystaticfuncgenerateRandomTokenRand()->String{vartoken=""for_in0..<16{letvalue=c_rand()%256token+=String(format:"%02x",value)}returntoken}//CryptographicallysecureonAppleplatforms//SwiftrandomAPIsuseSystemRandomNumberGeneratorbackedbythesystemCSPRNGviaarc4random_buf//ShownhereasasecuresourcethatisnotadedicatedcryptotokenAPIstaticfuncgenerateRandomTokenSwiftRandom()->String{vartoken=""for_in0..<16{letb=UInt8.random(in:0...255)token+=String(format:"%02x",b)}returntoken}//Cryptographicallysecure:directreadfrom/dev/randomonAppleplatforms//However,thisisalowlevelinterfaceandisdiscouragedinfavorofSecRandomCopyBytesstaticfuncgenerateRandomTokenDevRandom()->String{letcount=16letfd=open("/dev/random",O_RDONLY)iffd<0{return"Error opening /dev/random"}varbuffer=[UInt8](repeating:0,count:count)letreadCount=read(fd,&buffer,count)close(fd)ifreadCount!=count{return"Error reading /dev/random"}returnbuffer.map{String(format:"%02x",$0)}.joined()}//CryptographicallysecurebutdiscouragedasadirecttokenAPIinSwiftcode//becauseuseslegacyCstyleinterfacesthatareeasiertomisuse//OnAppleplatformsarc4random_uniformisstrong,butSecRandomCopyBytesorCryptoKitarepreferredstaticfuncgenerateRandomTokenArc4RandomUniform()->String{vartoken=""for_in0..<16{letvalue=arc4random_uniform(256)token+=String(format:"%02x",value)}returntoken}//CryptographicallysecurebutdiscouragedasadirecttokenAPI//OnAppleplatformsarc4randomisstrong,butitisnottherecommendedcryptoAPIstaticfuncgenerateRandomTokenArc4Random()->String{vartoken=""for_in0..<16{letvalue=arc4random()%256token+=String(format:"%02x",value)}returntoken}//Cryptographicallysecure:SystemRandomNumberGeneratorusesthesystemCSPRNG//Itissuitableforcryptographicuse,andCryptoKitbuildsonit//IncludedheretocontrastsecuregeneratorswithinsecureonesstaticfuncgenerateRandomTokenSystemRNG()->String{vartoken=""varrng=SystemRandomNumberGenerator()for_in0..<16{letb=UInt8.random(in:0...255,using:&rng)token+=String(format:"%02x",b)}returntoken}//Insecure:drand48usesa48bitlinearcongruentialgenerator//NotthreadsafeandnotsuitableforcryptographicpurposesstaticfuncgenerateRandomTokenDrand48()->String{vartoken=""for_in0..<16{letvalue=Int(drand48()*256.0)%256token+=String(format:"%02x",value)}returntoken}//Cryptographicallysecure:CCRandomGenerateBytesusesthesystemCSPRNG//Secure,butalowerlevelAPIthatisgenerallydiscouragedinfavorofSecRandomCopyBytesstaticfuncgenerateRandomTokenCC()->String{varbuffer=[UInt8](repeating:0,count:16)letstatus=CCRandomGenerateBytes(&buffer,buffer.count)ifstatus!=kCCSuccess{return"Error generating random bytes with CCRandomGenerateBytes"}returnbuffer.map{String(format:"%02x",$0)}.joined()}//Recommended:SecRandomCopyBytesisthehighlevel,ApplerecommendedAPIforsecurerandombytesstaticfuncgenerateRandomTokenSecRandom()->String{varrandomBytes=[UInt8](repeating:0,count:16)letstatus=SecRandomCopyBytes(kSecRandomDefault,randomBytes.count,&randomBytes)guardstatus==errSecSuccesselse{return"Error generating secure random bytes"}returnrandomBytes.map{String(format:"%02x",$0)}.joined()}staticfuncmastgTest(completion:@escaping(String)->Void){//Seedlibcrandwithcurrenttimeletnow=UInt32(time(nil))c_srand(now)//Exampleofseedingdrand48withtime,whichalsomakesitpredictableiftheseedisknown//srand48(time(nil))letvalue=""" Using libc rand seeded with time Token: \(generateRandomTokenRand()) Using Swift random API backed by SystemRandomNumberGenerator Token: \(generateRandomTokenSwiftRandom()) Using /dev/random low level interface Token: \(generateRandomTokenDevRandom()) Using arc4random_uniform as a direct token source Token: \(generateRandomTokenArc4RandomUniform()) Using arc4random as a direct token source Token: \(generateRandomTokenArc4Random()) Using SystemRandomNumberGenerator directly Token: \(generateRandomTokenSystemRNG()) Using drand48 linear congruential generator Token: \(generateRandomTokenDrand48()) Using CCRandomGenerateBytes lower level API Token: \(generateRandomTokenCC()) Using SecRandomCopyBytes Token: \(generateRandomTokenSecRandom()) """completion(value)}}
The same output also shows calls to secure sources such as SecRandomCopyBytes, CCRandomGenerateBytes, SystemRandomNumberGenerator, and the Swift standard library's FixedWidthInteger.random implementation. These are present in the sample for contrast, but they are not the reason the test fails.