PKCS1v15.swift 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //
  2. // CryptoSwift
  3. //
  4. // Copyright (C) 2014-2021 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. // PKCS is a group of public-key cryptography standards devised
  16. // and published by RSA Security Inc, starting in the early 1990s.
  17. //
  18. /// EMSA PKCS1 v1.5 Padding Scheme
  19. ///
  20. /// The EMSA Version of the PKCS1 v1.5 padding scheme is **deterministic** (it pads the messages contents with 255 value bytes)
  21. /// ```
  22. /// // The returned structure
  23. /// // - PS is the applied padding
  24. /// // - M is your original Message
  25. /// EM = 0x00 || 0x01 || PS || 0x00 || M.
  26. /// ```
  27. /// - Note: This Padding scheme is intended to be used for encoding RSA Signatures
  28. struct EMSAPKCS1v15Padding: PaddingProtocol {
  29. init() {
  30. }
  31. @inlinable
  32. func add(to bytes: Array<UInt8>, blockSize: Int) -> Array<UInt8> {
  33. var r = blockSize - ((bytes.count + 3) % blockSize)
  34. if r <= 0 { r = blockSize - 3 }
  35. return [0x00, 0x01] + Array<UInt8>(repeating: 0xFF, count: r) + [0x00] + bytes
  36. }
  37. @inlinable
  38. func remove(from bytes: Array<UInt8>, blockSize _: Int?) -> Array<UInt8> {
  39. assert(!bytes.isEmpty, "Need bytes to remove padding")
  40. assert(bytes.prefix(2) == [0x00, 0x01], "Invalid padding prefix")
  41. guard let paddingLength = bytes.dropFirst(2).firstIndex(of: 0x00) else { return bytes }
  42. guard (paddingLength + 1) <= bytes.count else { return bytes }
  43. return Array(bytes[(paddingLength + 1)...])
  44. }
  45. }
  46. /// EME PKCS1 v1.5 Padding Scheme
  47. ///
  48. /// The EME Version of the PKCS1 v1.5 padding scheme is **non deterministic** (it pads the messages contents with psuedo-random bytes)
  49. /// ```
  50. /// // The returned structure
  51. /// // - PS is the applied padding
  52. /// // - M is your original Message
  53. /// EM = 0x00 || 0x02 || PS || 0x00 || M.
  54. /// ```
  55. /// - Note: This Padding scheme is intended to be used for encoding messages before RSA Encryption
  56. struct EMEPKCS1v15Padding: PaddingProtocol {
  57. init() {
  58. }
  59. @inlinable
  60. func add(to bytes: Array<UInt8>, blockSize: Int) -> Array<UInt8> {
  61. var r = blockSize - ((bytes.count + 3) % blockSize)
  62. if r <= 0 { r = blockSize - 3 }
  63. return [0x00, 0x02] + (0..<r).map { _ in UInt8.random(in: 1...UInt8.max) } + [0x00] + bytes
  64. }
  65. @inlinable
  66. func remove(from bytes: Array<UInt8>, blockSize _: Int?) -> Array<UInt8> {
  67. assert(!bytes.isEmpty, "Need bytes to remove padding")
  68. assert(bytes.prefix(2) == [0x00, 0x02], "Invalid padding prefix")
  69. guard let paddingLength = bytes.dropFirst(2).firstIndex(of: 0x00) else { return bytes }
  70. guard (paddingLength + 1) <= bytes.count else { return bytes }
  71. return Array(bytes[(paddingLength + 1)...])
  72. }
  73. }