@ -41,6 +41,15 @@ extension Sign {
}
}
// / T h e s e e x t e n i o n m e t h o d s a r e u s e d t o g e n e r a t e a s i g n " b l i n d e d " m e s s a g e s
// /
// / A c c o r d i n g t o t h e S w i f t e n g i n e e r s t h e o n l y s i t u a t i o n w h e n ` U n s a f e R a w B u f f e r P o i n t e r . b a s e A d d r e s s ` i s n i l i s w h e n i t ' s a n
// / e m p t y c o l l e c t i o n ; a s s u c h o u r g u a r d c a s e s w i h c h r e t u r n ` - 1 ` w h e n u n w r a p p i n g t h i s v a l u e s h o u l d n e v e r b e h i t a n d w e c a n i g n o r e
// / t h e m a s p o s s i b l e r e s u l t s .
// /
// / F o r m o r e i n f o r m a t i o n s e e :
// / h t t p s : / / f o r u m s . s w i f t . o r g / t / w h e n - i s - u n s a f e m u t a b l e b u f f e r p o i n t e r - b a s e a d d r e s s - n i l / 3 2 1 3 6 / 5
// / h t t p s : / / g i t h u b . c o m / a p p l e / s w i f t - e v o l u t i o n / b l o b / m a s t e r / p r o p o s a l s / 0 0 5 5 - o p t i o n a l - u n s a f e - p o i n t e r s . m d # u n s a f e b u f f e r p o i n t e r
extension Sodium {
private static let scalarLength : Int = Int ( crypto_core_ed25519_scalarbytes ( ) ) // 3 2
private static let noClampLength : Int = Int ( crypto_scalarmult_ed25519_bytes ( ) ) // 3 2
@ -49,7 +58,7 @@ extension Sodium {
private static let secretKeyLength : Int = Int ( crypto_sign_secretkeybytes ( ) ) // 6 4
// / 6 4 - b y t e b l a k e 2 b h a s h t h e n r e d u c e t o g e t t h e b l i n d i n g f a c t o r
public func generateBlindingFactor ( serverPublicKey : String ) -> Bytes ? {
public func generateBlindingFactor ( serverPublicKey : String , genericHash : GenericHashType ) -> Bytes ? {
// / k = s a l t . c r y p t o _ c o r e _ e d 2 5 5 1 9 _ s c a l a r _ r e d u c e ( b l a k e 2 b ( s e r v e r _ p k , d i g e s t _ s i z e = 6 4 ) . d i g e s t ( ) )
guard let serverPubKeyData : Data = serverPublicKey . dataFromHex ( ) else { return nil }
guard let serverPublicKeyHashBytes : Bytes = genericHash . hash ( message : [ UInt8 ] ( serverPubKeyData ) , outputLength : 64 ) else {
@ -59,18 +68,15 @@ extension Sodium {
// / R e d u c e t h e s e r v e r p u b l i c k e y i n t o a n e d 2 5 5 1 9 s c a l a r ( ` k ` )
let kPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . scalarLength )
let kResult = serverPublicKeyHashBytes . withUnsafeBytes { ( serverPublicKeyHashPtr : UnsafeRawBufferPointer ) -> Int32 in
_ = serverPublicKeyHashBytes . withUnsafeBytes { ( serverPublicKeyHashPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let serverPublicKeyHashBaseAddress : UnsafePointer < UInt8 > = serverPublicKeyHashPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
crypto_core_ed25519_scalar_reduce ( kPtr , serverPublicKeyHashBaseAddress )
return 0
}
// / E n s u r e t h e a b o v e w o r k e d
guard kResult = = 0 else { return nil }
return Data ( bytes : kPtr , count : Sodium . scalarLength ) . bytes
}
@ -78,21 +84,20 @@ extension Sodium {
// / c o n v e r t t o a n * x * s e c r e t k e y , w h i c h s e e m s w r o n g - - b u t i s n ' t b e c a u s e c o n v e r t e d k e y s u s e t h e
// / s a m e s e c r e t s c a l a r s e c r e t ( a n d s o t h i s i s j u s t t h e m o s t c o n v e n i e n t w a y t o g e t ' a ' o u t o f
// / a s o d i u m E d 2 5 5 1 9 s e c r e t k e y )
private func generatePrivateKeyScalar ( secretKey : Bytes ) -> Bytes ? {
func generatePrivateKeyScalar ( secretKey : Bytes ) -> Bytes {
// / a = s . t o _ c u r v e 2 5 5 1 9 _ p r i v a t e _ k e y ( ) . e n c o d e ( )
let aPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . scalarMultLength )
let aResult = secretKey . withUnsafeBytes { ( secretKeyPtr : UnsafeRawBufferPointer ) -> Int32 in
// / L o o k s l i k e t h e ` c r y p t o _ s i g n _ e d 2 5 5 1 9 _ s k _ t o _ c u r v e 2 5 5 1 9 ` f u n c t i o n c a n ' t a c t u a l l y f a i l s o n o n e e d t o v e r i f y t h e r e s u l t
// / S e e : h t t p s : / / g i t h u b . c o m / j e d i s c t 1 / l i b s o d i u m / b l o b / m a s t e r / s r c / l i b s o d i u m / c r y p t o _ s i g n / e d 2 5 5 1 9 / r e f 1 0 / k e y p a i r . c # L 7 0
_ = secretKey . withUnsafeBytes { ( secretKeyPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let secretKeyBaseAddress : UnsafePointer < UInt8 > = secretKeyPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
return crypto_sign_ed25519_sk_to_curve25519 ( aPtr , secretKeyBaseAddress )
}
// / E n s u r e t h e a b o v e w o r k e d
guard aResult = = 0 else { return nil }
return Data ( bytes : aPtr , count : Sodium . scalarMultLength ) . bytes
}
@ -101,20 +106,22 @@ extension Sodium {
guard edKeyPair . publicKey . count = = Sodium . publicKeyLength && edKeyPair . secretKey . count = = Sodium . secretKeyLength else {
return nil
}
guard let kBytes : Bytes = generateBlindingFactor ( serverPublicKey : serverPublicKey ) else { return nil }
guard let aBytes : Bytes = generatePrivateKeyScalar ( secretKey : edKeyPair . secretKey ) else { return nil }
guard let kBytes : Bytes = generateBlindingFactor ( serverPublicKey : serverPublicKey , genericHash : genericHash ) else {
return nil
}
let aBytes : Bytes = generatePrivateKeyScalar ( secretKey : edKeyPair . secretKey )
// / G e n e r a t e t h e b l i n d e d k e y p a i r ` k a ` , ` k A `
let kaPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . secretKeyLength )
let kAPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . publicKeyLength )
let kaResult = aBytes . withUnsafeBytes { ( aPtr : UnsafeRawBufferPointer ) -> Int32 in
_ = aBytes . withUnsafeBytes { ( aPtr : UnsafeRawBufferPointer ) -> Int32 in
return kBytes . withUnsafeBytes { ( kPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let kBaseAddress : UnsafePointer < UInt8 > = kPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
guard let aBaseAddress : UnsafePointer < UInt8 > = aPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
crypto_core_ed25519_scalar_mul ( kaPtr , kBaseAddress , aBaseAddress )
@ -122,9 +129,6 @@ extension Sodium {
}
}
// / E n s u r e t h e a b o v e w o r k e d
guard kaResult = = 0 else { return nil }
guard crypto_scalarmult_ed25519_base_noclamp ( kAPtr , kaPtr ) = = 0 else { return nil }
return Box . KeyPair (
@ -144,18 +148,15 @@ extension Sodium {
let combinedHashBytes : Bytes = ( H_rh + kA + message ) . sha512 ( )
let rPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . scalarLength )
let rResult = combinedHashBytes . withUnsafeBytes { ( combinedHashPtr : UnsafeRawBufferPointer ) -> Int32 in
_ = combinedHashBytes . withUnsafeBytes { ( combinedHashPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let combinedHashBaseAddress : UnsafePointer < UInt8 > = combinedHashPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
crypto_core_ed25519_scalar_reduce ( rPtr , combinedHashBaseAddress )
return 0
}
// / E n s u r e t h e a b o v e w o r k e d
guard rResult = = 0 else { return nil }
// / s i g _ R = s a l t . c r y p t o _ s c a l a r m u l t _ e d 2 5 5 1 9 _ b a s e _ n o c l a m p ( r )
let sig_RPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . noClampLength )
guard crypto_scalarmult_ed25519_base_noclamp ( sig_RPtr , rPtr ) = = 0 else { return nil }
@ -165,25 +166,22 @@ extension Sodium {
let HRAMHashBytes : Bytes = ( sig_RBytes + kA + message ) . sha512 ( )
let HRAMPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . scalarLength )
let HRAMResult = HRAMHashBytes . withUnsafeBytes { ( HRAMHashPtr : UnsafeRawBufferPointer ) -> Int32 in
_ = HRAMHashBytes . withUnsafeBytes { ( HRAMHashPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let HRAMHashBaseAddress : UnsafePointer < UInt8 > = HRAMHashPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
crypto_core_ed25519_scalar_reduce ( HRAMPtr , HRAMHashBaseAddress )
return 0
}
// / E n s u r e t h e a b o v e w o r k e d
guard HRAMResult = = 0 else { return nil }
// / s i g _ s = s a l t . c r y p t o _ c o r e _ e d 2 5 5 1 9 _ s c a l a r _ a d d ( r , s a l t . c r y p t o _ c o r e _ e d 2 5 5 1 9 _ s c a l a r _ m u l ( H R A M , k a ) )
let sig_sMulPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . scalarLength )
let sig_sPtr : UnsafeMutablePointer < UInt8 > = UnsafeMutablePointer < UInt8 > . allocate ( capacity : Sodium . scalarLength )
let sig _sResult = ka . withUnsafeBytes { ( kaPtr : UnsafeRawBufferPointer ) -> Int32 in
_ = ka . withUnsafeBytes { ( kaPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let kaBaseAddress : UnsafePointer < UInt8 > = kaPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
crypto_core_ed25519_scalar_mul ( sig_sMulPtr , HRAMPtr , kaBaseAddress )
@ -191,8 +189,6 @@ extension Sodium {
return 0
}
guard sig_sResult = = 0 else { return nil }
// / f u l l _ s i g = s i g _ R + s i g _ s
return ( Data ( bytes : sig_RPtr , count : Sodium . noClampLength ) . bytes + Data ( bytes : sig_sPtr , count : Sodium . scalarLength ) . bytes )
}
@ -204,10 +200,10 @@ extension Sodium {
let result = rhsKeyBytes . withUnsafeBytes { ( rhsKeyBytesPtr : UnsafeRawBufferPointer ) -> Int32 in
return lhsKeyBytes . withUnsafeBytes { ( lhsKeyBytesPtr : UnsafeRawBufferPointer ) -> Int32 in
guard let lhsKeyBytesBaseAddress : UnsafePointer < UInt8 > = lhsKeyBytesPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
guard let rhsKeyBytesBaseAddress : UnsafePointer < UInt8 > = rhsKeyBytesPtr . baseAddress ? . assumingMemoryBound ( to : UInt8 . self ) else {
return - 1
return - 1 // I m p o s s i b l e c a s e ( r e f e r t o c o m m e n t s a t t o p o f e x t e n s i o n )
}
return crypto_scalarmult_ed25519_noclamp ( combinedPtr , lhsKeyBytesBaseAddress , rhsKeyBytesBaseAddress )
@ -228,18 +224,23 @@ extension Sodium {
// /
// / B L A K E 2 b ( b k A | | k A | | k B )
public func sharedBlindedEncryptionKey ( secretKey : Bytes , otherBlindedPublicKey : Bytes , fromBlindedPublicKey kA : Bytes , toBlindedPublicKey kB : Bytes , genericHash : GenericHashType ) -> Bytes ? {
guard let aBytes : Bytes = generatePrivateKeyScalar ( secretKey : secretKey ) else { return nil }
guard let combinedKeyBytes : Bytes = combineKeys ( lhsKeyBytes : aBytes , rhsKeyBytes : otherBlindedPublicKey ) else { return nil }
let aBytes : Bytes = generatePrivateKeyScalar ( secretKey : secretKey )
guard let combinedKeyBytes : Bytes = combineKeys ( lhsKeyBytes : aBytes , rhsKeyBytes : otherBlindedPublicKey ) else {
return nil
}
return genericHash . hash ( message : ( combinedKeyBytes + kA + kB ) , outputLength : 32 )
}
// / T h i s m e t h o d s h o u l d b e u s e d t o c h e c k i f a u s e r s s t a n d a r d s e s s i o n I d m a t c h e s a b l i n d e d o n e
public func sessionId ( _ standardSessionId : String , matchesBlindedId blindedSessionId : String , serverPublicKey : String ) -> Bool {
public func sessionId ( _ standardSessionId : String , matchesBlindedId blindedSessionId : String , serverPublicKey : String , genericHash : GenericHashType ) -> Bool {
// O n l y s u p p o r t g e n e r a t i n g b l i n d e d k e y s f o r s t a n d a r d s e s s i o n i d s
guard let sessionId : SessionId = SessionId ( from : standardSessionId ) , sessionId . prefix = = . standard else { return false }
guard let blindedId : SessionId = SessionId ( from : blindedSessionId ) , blindedId . prefix = = . blinded else { return false }
guard let kBytes : Bytes = generateBlindingFactor ( serverPublicKey : serverPublicKey ) else { return false }
guard let kBytes : Bytes = generateBlindingFactor ( serverPublicKey : serverPublicKey , genericHash : genericHash ) else {
return false
}
// / F r o m t h e s e s s i o n i d ( i g n o r i n g 0 5 p r e f i x ) w e h a v e t w o p o s s i b l e e d 2 5 5 1 9 p u b k e y s ; t h e f i r s t i s t h e p o s i t i v e ( w h i c h i s w h a t
// / S i g n a l ' s X E d 2 5 5 1 9 c o n v e r s i o n a l w a y s u s e s )