SecureBytes.swift 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //
  2. // CryptoSwift
  3. //
  4. // Copyright (C) 2014-2025 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
  5. // This software is provided 'as-is', without any express or implied warranty.
  6. //
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
  10. //
  11. // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
  12. // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  13. // - This notice may not be removed or altered from any source or binary distribution.
  14. //
  15. #if canImport(Darwin)
  16. import Darwin
  17. #elseif canImport(Glibc)
  18. import Glibc
  19. #elseif canImport(Musl)
  20. import Musl
  21. #elseif canImport(WinSDK)
  22. import WinSDK
  23. #endif
  24. typealias Key = SecureBytes
  25. /// Keeps bytes in memory. Because this is class, bytes are not copied
  26. /// and memory area is locked as long as referenced, then unlocked on deinit
  27. final class SecureBytes {
  28. private let bytes: Array<UInt8>
  29. let count: Int
  30. init(bytes: Array<UInt8>) {
  31. self.bytes = bytes
  32. self.count = bytes.count
  33. self.bytes.withUnsafeBufferPointer { (pointer) -> Void in
  34. #if os(Windows)
  35. VirtualLock(UnsafeMutableRawPointer(mutating: pointer.baseAddress), SIZE_T(pointer.count))
  36. #elseif os(WASI)
  37. // not supported on WASI
  38. #else
  39. mlock(pointer.baseAddress, pointer.count)
  40. #endif
  41. }
  42. }
  43. deinit {
  44. self.bytes.withUnsafeBufferPointer { (pointer) -> Void in
  45. #if os(Windows)
  46. VirtualUnlock(UnsafeMutableRawPointer(mutating: pointer.baseAddress), SIZE_T(pointer.count))
  47. #elseif os(WASI)
  48. // not supported on WASI
  49. #else
  50. munlock(pointer.baseAddress, pointer.count)
  51. #endif
  52. }
  53. }
  54. }
  55. extension SecureBytes: Collection {
  56. typealias Index = Int
  57. var endIndex: Int {
  58. self.bytes.endIndex
  59. }
  60. var startIndex: Int {
  61. self.bytes.startIndex
  62. }
  63. subscript(position: Index) -> UInt8 {
  64. self.bytes[position]
  65. }
  66. subscript(bounds: Range<Index>) -> ArraySlice<UInt8> {
  67. self.bytes[bounds]
  68. }
  69. func formIndex(after i: inout Int) {
  70. self.bytes.formIndex(after: &i)
  71. }
  72. func index(after i: Int) -> Int {
  73. self.bytes.index(after: i)
  74. }
  75. }
  76. extension SecureBytes: ExpressibleByArrayLiteral {
  77. public convenience init(arrayLiteral elements: UInt8...) {
  78. self.init(bytes: elements)
  79. }
  80. }