2014-12-31 8 views
22

Sto scrivendo un'applicazione rapida che richiede la gestione di chiavi private in memoria. A causa della sensibilità di tali oggetti, i tasti devono essere cancellati (a.k.a. scritti su tutti gli zeri) quando l'oggetto viene deallocato e la memoria non può essere paginata su disco (che viene tipicamente eseguita usando mlock()).Secure Memory per oggetti Swift

In Objective-C, è possibile fornire un oggetto CFAllocator personalizzato, che consente di utilizzare le proprie funzioni per allocare/deallocare/riallocare la memoria utilizzata da un oggetto.

Quindi una soluzione è implementare semplicemente un oggetto "SecureData" in ogg-c, che crea internamente un oggetto NSMutableData utilizzando un CFAllocator personalizzato (anche in ogg-c).

Tuttavia, esiste un modo per fornire le mie funzioni di allocazione della memoria personalizzate per un oggetto swift puro (ad esempio, una struct o [UInt8])? O c'è un modo migliore, "corretto" per implementare la memoria sicura come questa in modo rapido?

+0

Perché non si implementa semplicemente il metodo di deinit dell'oggetto che detiene la chiave e che cancella la chiave? – CouchDeveloper

+0

@ 0x7fffffff - che tipo di informazioni aggiuntive stai cercando su ciò che la mia risposta ha dato? Avrò un tentativo di aggiungerlo. –

+0

@AirspeedVelocity La risposta che hai dato è già eccezionale. Se non altro, sto solo cercando un altro esempio, o se possibile, una spiegazione di come si potrebbe cercare di aggirare i problemi associati con le stringhe e gli array. (principalmente solo stringhe) Grazie per il seguito. –

risposta

26

Se si vuole il controllo completo su una regione di memoria allocare voi stessi, potete utilizzare UnsafePointer e co:

// allocate enough memory for ten Ints 
var ump = UnsafeMutablePointer<Int>.alloc(10) 
// memory is in an uninitialized raw state 

// initialize that memory with Int objects 
// (here, from a collection) 
ump.initializeFrom(reverse(0..<10)) 

// memory property gives you access to the underlying value 
ump.memory // 9 

// UnsafeMutablePointer acts like an IndexType 
ump.successor().memory // 8 
// and it has a subscript, but it's not a CollectionType 
ump[3] // = 6 

// wrap it in an UnsafeMutableBufferPointer to treat it 
// like a collection (or UnsafeBufferPointer if you don't 
// need to be able to alter the values) 
let col = UnsafeMutableBufferPointer(start: ump, count: 10) 
col[3] = 99 
println(",".join(map(col,toString))) 
// prints 9,8,7,99,5,4,3,2,1,0 

ump.destroy(10) 
// now the allocated memory is back in a raw state 
// you could re-allocate it... 
ump.initializeFrom(0..<10) 
ump.destroy(10) 

// when you're done, deallocate the memory 
ump.dealloc(10) 

Si può anche avere UnsafePointer punto a un'altra memoria, come la memoria si sta consegnato da alcune API C.

UnsafePointer può essere passato in funzioni C che portano un puntatore a un blocco contiguo di memoria. Quindi, per i vostri scopi, si potrebbe quindi passare questo puntatore in una funzione simile mlock:

let count = 10 
let ump = UnsafeMutablePointer.allocate<Int>(count) 
mlock(ump, UInt(sizeof(Int) * count)) 
// initialize, use, and destroy the memory 
munlock(ump, UInt(sizeof(Int) * count)) 
ump.dealloc(count) 

È anche possibile tenere il proprio tipi personalizzati:

struct MyStruct { 
    let a: Int 
    let b: Int 
} 

var pointerToStruct = UnsafeMutablePointer<MyStruct>.alloc(1) 
pointerToStruct.initialize(MyStruct(a: 1, b: 2)) 
pointerToStruct.memory.b // 2 
pointerToStruct.destroy() 
pointerToStruct.dealloc(1) 

Tuttavia essere a conoscenza se fare questo con le classi o anche array o stringhe (o una struttura che li contiene), che tutto ciò che si terrà nella memoria è puntatori ad altra memoria che questi oggetti allocano e possiedono. Se questo è importante per te (ad esempio stai facendo qualcosa di speciale in questa memoria, ad esempio la sicurezza, nel tuo esempio), probabilmente non è ciò che desideri.

Quindi è necessario utilizzare oggetti di dimensioni fisse o utilizzare ulteriormente UnsafePointer per mantenere i puntatori su più aree di memoria. Se non hanno bisogno di ridimensionare dinamicamente, solo una singola allocazione di un puntatore non sicuro, possibilmente racchiuso in un interfaccia UnsafeBufferPointer per un'interfaccia di raccolta, potrebbe farlo.

Se avete bisogno di un comportamento più dinamico, sotto è un'implementazione molto ridotta all'osso di una collezione che può ridimensionare, se necessario, che potrebbe essere valorizzato per coprire specialità memoria logica di gestione:

// Note this is a class not a struct, so it does NOT have value semantics, 
// changing a copy changes all copies. 
public class UnsafeCollection<T> { 
    private var _len: Int = 0 
    private var _buflen: Int = 0 
    private var _buf: UnsafeMutablePointer<T> = nil 

    public func removeAll(keepCapacity: Bool = false) { 
     _buf.destroy(_len) 
     _len = 0 
     if !keepCapacity { 
      _buf.dealloc(_buflen) 
      _buflen = 0 
      _buf = nil 
     } 
    } 

    public required init() { } 
    deinit { self.removeAll(keepCapacity: false) } 

    public var count: Int { return _len } 
    public var isEmpty: Bool { return _len == 0 } 
} 

per coprire le requisiti di MutableCollectionType (cioè CollectionType più pedice assegnabile):

extension UnsafeCollection: MutableCollectionType { 
    typealias Index = Int 
    public var startIndex: Int { return 0 } 
    public var endIndex: Int { return _len } 

    public subscript(idx: Int) -> T { 
     get { 
      precondition(idx < _len) 
      return _buf[idx] 
     } 
     set(newElement) { 
      precondition(idx < _len) 
      let ptr = _buf.advancedBy(idx) 
      ptr.destroy() 
      ptr.initialize(newElement) 
     } 
    } 

    typealias Generator = IndexingGenerator<UnsafeCollection> 
    public func generate() -> Generator { 
     return Generator(self) 
    } 
} 

E ExtensibleCollectionType, per consentire la crescita dinamica:

+0

Grazie! Questo sembra avere la maggior parte del modo lì. La memoria è allocata in un blocco contiguo? Ad esempio con questo codice: let myPtr = UnsafeMutablePointer .alloc (10) Farei quindi qualcosa come mlock (myPtr, 10) per impedire che la memoria venga cercata sul disco. – kgreenek

+0

Credo di sì (significa anche che puoi passarlo come un oggetto simile a un puntatore a forma di matrice nelle funzioni C) –