diff --git a/docs/Suzuri.html b/docs/Suzuri.html index 3349971..c93841c 100644 --- a/docs/Suzuri.html +++ b/docs/Suzuri.html @@ -173,7 +173,7 @@
Decodes a Suzuri token.
Use require "suzuri/json_serializable"
to add #to_suzuri
, #from_suzuri
and #from_suzuri_with_timestamp
methods to all JSON::Serializable
objects.
Decodes a Suzuri token.
","abstract":false,"args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"args_string":"(token : String, key : String, ttl : Time::Span? = nil) : Token","args_html":"(token : String, key : String, ttl : Time::Span? = nil) : Token","location":{"filename":"src/suzuri.cr","line_number":59,"url":null},"def":{"name":"decode","args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"return_type":"Token","visibility":"Public","body":"begin\n raw = Base64.decode(token)\nrescue ex : Exception\n raise(Error::MalformedInput.new(\"Base64 decoding failed\"))\nend\nbegin\n timestamp = Time.unix((IO::Memory.new(raw[1..4])).read_bytes(UInt32, IO::ByteFormat::BigEndian))\n header = raw[0..(Token::HEADER_SIZE - 1)]\n ciphertext = raw[Token::HEADER_SIZE..-1]\n nonce = Sodium::Nonce.new(raw[5..(4 + Token::NONCE_SIZE)])\nrescue ex : Exception\n raise(Error::MalformedInput.new(ex.message))\nend\nbegin\n cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\n payload = cipher.decrypt(ciphertext, nonce: nonce, additional: header.to_slice)\n if raw[0] == 129_u8\n dctx = Zstd::Decompress::Context.new\n payload = dctx.decompress(payload)\n end\nrescue ex : Sodium::Error::DecryptionFailed\n raise(Error::DecryptionFailed.new(ex.message))\nend\nif ttl && (timestamp + ttl) < Time.utc\n raise(Error::TokenExpired.new(\"Token expired at #{timestamp + ttl}\"))\nend\nToken.new(payload: payload, timestamp: timestamp)\n"}},{"html_id":"encode(payload:String|Bytes,key:String|Bytes,timestamp:Time=Time.utc,compress_level=3,compress_threshold:UInt64=512):String-class-method","name":"encode","doc":"Encodes a Suzuri token.\n\n**Examples:**\n```\n# Encode\nSuzuri.encode(\"hello world\", KEY) # => \"wB3AKYBaTwJc...\"\n\n# Encode with compression disabled\nSuzuri.encode(\"hello world\", KEY, compress_threshold: UInt64::MAX) # => \"xAJyiEKfPLPi...\"\n\n# Encode with a custom creation timestamp\nSuzuri.encode(\"hello world\", KEY, Time.utc(1985-10-26)) # => \"mArTYmcfLyYy...\"\n\n# Encode with a higher compression level. Value can be 1-19. Default is 3.\nSuzuri.encode(\"hello world\", KEY, compress_level: 10) # => \"puI8lSpoAox5...\"\n```","summary":"Encodes a Suzuri token.
","abstract":false,"args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"args_string":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","args_html":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","location":{"filename":"src/suzuri.cr","line_number":22,"url":null},"def":{"name":"encode","args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"return_type":"String","visibility":"Public","body":"cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\nnonce = Sodium::Nonce.random\nheader = IO::Memory.new(Token::HEADER_SIZE)\nheader.write_byte(payload.size > compress_threshold ? 129_u8 : 128_u8)\nheader.write_bytes(timestamp.to_unix.to_u32, IO::ByteFormat::BigEndian)\nheader.write(nonce.to_slice)\nif payload.size > compress_threshold\n cctx = Zstd::Compress::Context.new(level: compress_level)\n payload = cctx.compress(payload.to_slice)\nend\nciphertext, _ = cipher.encrypt(payload, nonce: nonce, additional: header.to_slice)\nraw = Bytes.new(header.size + ciphertext.size)\nheader.to_slice.move_to(raw)\nciphertext.move_to(raw + header.size)\nBase64.urlsafe_encode(raw.to_slice)\n"}}],"types":[{"html_id":"suzuri/Suzuri/Error","path":"Suzuri/Error.html","kind":"module","full_name":"Suzuri::Error","name":"Error","abstract":false,"locations":[{"filename":"src/suzuri.cr","line_number":90,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"types":[{"html_id":"suzuri/Suzuri/Error/DecodeError","path":"Suzuri/Error/DecodeError.html","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError","abstract":false,"superclass":{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},"ancestors":[{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":91,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed"},{"html_id":"suzuri/Suzuri/Error/MalformedInput","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput"},{"html_id":"suzuri/Suzuri/Error/TokenExpired","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired"}],"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","path":"Suzuri/Error/DecryptionFailed.html","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":94,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/MalformedInput","path":"Suzuri/Error/MalformedInput.html","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":92,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/TokenExpired","path":"Suzuri/Error/TokenExpired.html","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":93,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}}]},{"html_id":"suzuri/Suzuri/Token","path":"Suzuri/Token.html","kind":"struct","full_name":"Suzuri::Token","name":"Token","abstract":false,"superclass":{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"suzuri/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":97,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"instance_methods":[{"html_id":"payload:Bytes-instance-method","name":"payload","doc":"Returns the decrypted payload as `Bytes`","summary":"Returns the decrypted payload as Bytes
Returns the creation timestamp
","abstract":false,"location":{"filename":"src/suzuri.cr","line_number":106,"url":null},"def":{"name":"timestamp","return_type":"Time","visibility":"Public","body":"@timestamp"}},{"html_id":"to_s:String-instance-method","name":"to_s","doc":"Returns the decrypted payload as `String`","summary":"Returns the decrypted payload as String
Use require "suzuri/json_serializable"
to add #to_suzuri
, #from_suzuri
and #from_suzuri_with_timestamp
methods to all JSON::Serializable
objects.
Decodes a Suzuri token.
","abstract":false,"args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"args_string":"(token : String, key : String | Bytes, ttl : Time::Span? = nil) : Token","args_html":"(token : String, key : String | Bytes, ttl : Time::Span? = nil) : Token","location":{"filename":"src/suzuri.cr","line_number":59,"url":null},"def":{"name":"decode","args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"return_type":"Token","visibility":"Public","body":"begin\n raw = Base64.decode(token)\nrescue ex : Exception\n raise(Error::MalformedInput.new(\"Base64 decoding failed\"))\nend\nbegin\n timestamp = Time.unix((IO::Memory.new(raw[1..4])).read_bytes(UInt32, IO::ByteFormat::BigEndian))\n header = raw[0..(Token::HEADER_SIZE - 1)]\n ciphertext = raw[Token::HEADER_SIZE..-1]\n nonce = Sodium::Nonce.new(raw[5..(4 + Token::NONCE_SIZE)])\nrescue ex : Exception\n raise(Error::MalformedInput.new(ex.message))\nend\nbegin\n cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\n payload = cipher.decrypt(ciphertext, nonce: nonce, additional: header.to_slice)\n if raw[0] == 129_u8\n dctx = Zstd::Decompress::Context.new\n payload = dctx.decompress(payload)\n end\nrescue ex : Sodium::Error::DecryptionFailed\n raise(Error::DecryptionFailed.new(ex.message))\nend\nif ttl && (timestamp + ttl) < Time.utc\n raise(Error::TokenExpired.new(\"Token expired at #{timestamp + ttl}\"))\nend\nToken.new(payload: payload, timestamp: timestamp)\n"}},{"html_id":"encode(payload:String|Bytes,key:String|Bytes,timestamp:Time=Time.utc,compress_level=3,compress_threshold:UInt64=512):String-class-method","name":"encode","doc":"Encodes a Suzuri token.\n\n**Examples:**\n```\n# Encode\nSuzuri.encode(\"hello world\", KEY) # => \"wB3AKYBaTwJc...\"\n\n# Encode with compression disabled\nSuzuri.encode(\"hello world\", KEY, compress_threshold: UInt64::MAX) # => \"xAJyiEKfPLPi...\"\n\n# Encode with a custom creation timestamp\nSuzuri.encode(\"hello world\", KEY, Time.utc(1985-10-26)) # => \"mArTYmcfLyYy...\"\n\n# Encode with a higher compression level. Value can be 1-19. Default is 3.\nSuzuri.encode(\"hello world\", KEY, compress_level: 10) # => \"puI8lSpoAox5...\"\n```","summary":"Encodes a Suzuri token.
","abstract":false,"args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"args_string":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","args_html":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","location":{"filename":"src/suzuri.cr","line_number":22,"url":null},"def":{"name":"encode","args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"return_type":"String","visibility":"Public","body":"cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\nnonce = Sodium::Nonce.random\nheader = IO::Memory.new(Token::HEADER_SIZE)\nheader.write_byte(payload.size > compress_threshold ? 129_u8 : 128_u8)\nheader.write_bytes(timestamp.to_unix.to_u32, IO::ByteFormat::BigEndian)\nheader.write(nonce.to_slice)\nif payload.size > compress_threshold\n cctx = Zstd::Compress::Context.new(level: compress_level)\n payload = cctx.compress(payload.to_slice)\nend\nciphertext, _ = cipher.encrypt(payload, nonce: nonce, additional: header.to_slice)\nraw = Bytes.new(header.size + ciphertext.size)\nheader.to_slice.move_to(raw)\nciphertext.move_to(raw + header.size)\nBase64.urlsafe_encode(raw.to_slice)\n"}}],"types":[{"html_id":"suzuri/Suzuri/Error","path":"Suzuri/Error.html","kind":"module","full_name":"Suzuri::Error","name":"Error","abstract":false,"locations":[{"filename":"src/suzuri.cr","line_number":90,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"types":[{"html_id":"suzuri/Suzuri/Error/DecodeError","path":"Suzuri/Error/DecodeError.html","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError","abstract":false,"superclass":{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},"ancestors":[{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":91,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed"},{"html_id":"suzuri/Suzuri/Error/MalformedInput","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput"},{"html_id":"suzuri/Suzuri/Error/TokenExpired","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired"}],"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","path":"Suzuri/Error/DecryptionFailed.html","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":94,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/MalformedInput","path":"Suzuri/Error/MalformedInput.html","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":92,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/TokenExpired","path":"Suzuri/Error/TokenExpired.html","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":93,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}}]},{"html_id":"suzuri/Suzuri/Token","path":"Suzuri/Token.html","kind":"struct","full_name":"Suzuri::Token","name":"Token","abstract":false,"superclass":{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"suzuri/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":97,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"instance_methods":[{"html_id":"payload:Bytes-instance-method","name":"payload","doc":"Returns the decrypted payload as `Bytes`","summary":"Returns the decrypted payload as Bytes
Returns the creation timestamp
","abstract":false,"location":{"filename":"src/suzuri.cr","line_number":106,"url":null},"def":{"name":"timestamp","return_type":"Time","visibility":"Public","body":"@timestamp"}},{"html_id":"to_s:String-instance-method","name":"to_s","doc":"Returns the decrypted payload as `String`","summary":"Returns the decrypted payload as String
Use require "suzuri/json_serializable"
to add #to_suzuri
, #from_suzuri
and #from_suzuri_with_timestamp
methods to all JSON::Serializable
objects.
Decodes a Suzuri token.
","abstract":false,"args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"args_string":"(token : String, key : String, ttl : Time::Span? = nil) : Token","args_html":"(token : String, key : String, ttl : Time::Span? = nil) : Token","location":{"filename":"src/suzuri.cr","line_number":59,"url":null},"def":{"name":"decode","args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"return_type":"Token","visibility":"Public","body":"begin\n raw = Base64.decode(token)\nrescue ex : Exception\n raise(Error::MalformedInput.new(\"Base64 decoding failed\"))\nend\nbegin\n timestamp = Time.unix((IO::Memory.new(raw[1..4])).read_bytes(UInt32, IO::ByteFormat::BigEndian))\n header = raw[0..(Token::HEADER_SIZE - 1)]\n ciphertext = raw[Token::HEADER_SIZE..-1]\n nonce = Sodium::Nonce.new(raw[5..(4 + Token::NONCE_SIZE)])\nrescue ex : Exception\n raise(Error::MalformedInput.new(ex.message))\nend\nbegin\n cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\n payload = cipher.decrypt(ciphertext, nonce: nonce, additional: header.to_slice)\n if raw[0] == 129_u8\n dctx = Zstd::Decompress::Context.new\n payload = dctx.decompress(payload)\n end\nrescue ex : Sodium::Error::DecryptionFailed\n raise(Error::DecryptionFailed.new(ex.message))\nend\nif ttl && (timestamp + ttl) < Time.utc\n raise(Error::TokenExpired.new(\"Token expired at #{timestamp + ttl}\"))\nend\nToken.new(payload: payload, timestamp: timestamp)\n"}},{"html_id":"encode(payload:String|Bytes,key:String|Bytes,timestamp:Time=Time.utc,compress_level=3,compress_threshold:UInt64=512):String-class-method","name":"encode","doc":"Encodes a Suzuri token.\n\n**Examples:**\n```\n# Encode\nSuzuri.encode(\"hello world\", KEY) # => \"wB3AKYBaTwJc...\"\n\n# Encode with compression disabled\nSuzuri.encode(\"hello world\", KEY, compress_threshold: UInt64::MAX) # => \"xAJyiEKfPLPi...\"\n\n# Encode with a custom creation timestamp\nSuzuri.encode(\"hello world\", KEY, Time.utc(1985-10-26)) # => \"mArTYmcfLyYy...\"\n\n# Encode with a higher compression level. Value can be 1-19. Default is 3.\nSuzuri.encode(\"hello world\", KEY, compress_level: 10) # => \"puI8lSpoAox5...\"\n```","summary":"Encodes a Suzuri token.
","abstract":false,"args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"args_string":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","args_html":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","location":{"filename":"src/suzuri.cr","line_number":22,"url":null},"def":{"name":"encode","args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"return_type":"String","visibility":"Public","body":"cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\nnonce = Sodium::Nonce.random\nheader = IO::Memory.new(Token::HEADER_SIZE)\nheader.write_byte(payload.size > compress_threshold ? 129_u8 : 128_u8)\nheader.write_bytes(timestamp.to_unix.to_u32, IO::ByteFormat::BigEndian)\nheader.write(nonce.to_slice)\nif payload.size > compress_threshold\n cctx = Zstd::Compress::Context.new(level: compress_level)\n payload = cctx.compress(payload.to_slice)\nend\nciphertext, _ = cipher.encrypt(payload, nonce: nonce, additional: header.to_slice)\nraw = Bytes.new(header.size + ciphertext.size)\nheader.to_slice.move_to(raw)\nciphertext.move_to(raw + header.size)\nBase64.urlsafe_encode(raw.to_slice)\n"}}],"types":[{"html_id":"suzuri/Suzuri/Error","path":"Suzuri/Error.html","kind":"module","full_name":"Suzuri::Error","name":"Error","abstract":false,"locations":[{"filename":"src/suzuri.cr","line_number":90,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"types":[{"html_id":"suzuri/Suzuri/Error/DecodeError","path":"Suzuri/Error/DecodeError.html","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError","abstract":false,"superclass":{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},"ancestors":[{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":91,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed"},{"html_id":"suzuri/Suzuri/Error/MalformedInput","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput"},{"html_id":"suzuri/Suzuri/Error/TokenExpired","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired"}],"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","path":"Suzuri/Error/DecryptionFailed.html","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":94,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/MalformedInput","path":"Suzuri/Error/MalformedInput.html","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":92,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/TokenExpired","path":"Suzuri/Error/TokenExpired.html","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":93,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}}]},{"html_id":"suzuri/Suzuri/Token","path":"Suzuri/Token.html","kind":"struct","full_name":"Suzuri::Token","name":"Token","abstract":false,"superclass":{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"suzuri/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":97,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"instance_methods":[{"html_id":"payload:Bytes-instance-method","name":"payload","doc":"Returns the decrypted payload as `Bytes`","summary":"Returns the decrypted payload as Bytes
Returns the creation timestamp
","abstract":false,"location":{"filename":"src/suzuri.cr","line_number":106,"url":null},"def":{"name":"timestamp","return_type":"Time","visibility":"Public","body":"@timestamp"}},{"html_id":"to_s:String-instance-method","name":"to_s","doc":"Returns the decrypted payload as `String`","summary":"Returns the decrypted payload as String
Use require "suzuri/json_serializable"
to add #to_suzuri
, #from_suzuri
and #from_suzuri_with_timestamp
methods to all JSON::Serializable
objects.
Decodes a Suzuri token.
","abstract":false,"args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"args_string":"(token : String, key : String | Bytes, ttl : Time::Span? = nil) : Token","args_html":"(token : String, key : String | Bytes, ttl : Time::Span? = nil) : Token","location":{"filename":"src/suzuri.cr","line_number":59,"url":null},"def":{"name":"decode","args":[{"name":"token","external_name":"token","restriction":"String"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"ttl","default_value":"nil","external_name":"ttl","restriction":"Time::Span | ::Nil"}],"return_type":"Token","visibility":"Public","body":"begin\n raw = Base64.decode(token)\nrescue ex : Exception\n raise(Error::MalformedInput.new(\"Base64 decoding failed\"))\nend\nbegin\n timestamp = Time.unix((IO::Memory.new(raw[1..4])).read_bytes(UInt32, IO::ByteFormat::BigEndian))\n header = raw[0..(Token::HEADER_SIZE - 1)]\n ciphertext = raw[Token::HEADER_SIZE..-1]\n nonce = Sodium::Nonce.new(raw[5..(4 + Token::NONCE_SIZE)])\nrescue ex : Exception\n raise(Error::MalformedInput.new(ex.message))\nend\nbegin\n cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\n payload = cipher.decrypt(ciphertext, nonce: nonce, additional: header.to_slice)\n if raw[0] == 129_u8\n dctx = Zstd::Decompress::Context.new\n payload = dctx.decompress(payload)\n end\nrescue ex : Sodium::Error::DecryptionFailed\n raise(Error::DecryptionFailed.new(ex.message))\nend\nif ttl && (timestamp + ttl) < Time.utc\n raise(Error::TokenExpired.new(\"Token expired at #{timestamp + ttl}\"))\nend\nToken.new(payload: payload, timestamp: timestamp)\n"}},{"html_id":"encode(payload:String|Bytes,key:String|Bytes,timestamp:Time=Time.utc,compress_level=3,compress_threshold:UInt64=512):String-class-method","name":"encode","doc":"Encodes a Suzuri token.\n\n**Examples:**\n```\n# Encode\nSuzuri.encode(\"hello world\", KEY) # => \"wB3AKYBaTwJc...\"\n\n# Encode with compression disabled\nSuzuri.encode(\"hello world\", KEY, compress_threshold: UInt64::MAX) # => \"xAJyiEKfPLPi...\"\n\n# Encode with a custom creation timestamp\nSuzuri.encode(\"hello world\", KEY, Time.utc(1985-10-26)) # => \"mArTYmcfLyYy...\"\n\n# Encode with a higher compression level. Value can be 1-19. Default is 3.\nSuzuri.encode(\"hello world\", KEY, compress_level: 10) # => \"puI8lSpoAox5...\"\n```","summary":"Encodes a Suzuri token.
","abstract":false,"args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"args_string":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","args_html":"(payload : String | Bytes, key : String | Bytes, timestamp : Time = Time.utc, compress_level = 3, compress_threshold : UInt64 = 512) : String","location":{"filename":"src/suzuri.cr","line_number":22,"url":null},"def":{"name":"encode","args":[{"name":"payload","external_name":"payload","restriction":"String | Bytes"},{"name":"key","external_name":"key","restriction":"String | Bytes"},{"name":"timestamp","default_value":"Time.utc","external_name":"timestamp","restriction":"Time"},{"name":"compress_level","default_value":"3","external_name":"compress_level","restriction":""},{"name":"compress_threshold","default_value":"512","external_name":"compress_threshold","restriction":"UInt64"}],"return_type":"String","visibility":"Public","body":"cipher = Token::CIPHER.new(Sodium::SecureBuffer.copy_from(key.to_slice))\nnonce = Sodium::Nonce.random\nheader = IO::Memory.new(Token::HEADER_SIZE)\nheader.write_byte(payload.size > compress_threshold ? 129_u8 : 128_u8)\nheader.write_bytes(timestamp.to_unix.to_u32, IO::ByteFormat::BigEndian)\nheader.write(nonce.to_slice)\nif payload.size > compress_threshold\n cctx = Zstd::Compress::Context.new(level: compress_level)\n payload = cctx.compress(payload.to_slice)\nend\nciphertext, _ = cipher.encrypt(payload, nonce: nonce, additional: header.to_slice)\nraw = Bytes.new(header.size + ciphertext.size)\nheader.to_slice.move_to(raw)\nciphertext.move_to(raw + header.size)\nBase64.urlsafe_encode(raw.to_slice)\n"}}],"types":[{"html_id":"suzuri/Suzuri/Error","path":"Suzuri/Error.html","kind":"module","full_name":"Suzuri::Error","name":"Error","abstract":false,"locations":[{"filename":"src/suzuri.cr","line_number":90,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"types":[{"html_id":"suzuri/Suzuri/Error/DecodeError","path":"Suzuri/Error/DecodeError.html","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError","abstract":false,"superclass":{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},"ancestors":[{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":91,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed"},{"html_id":"suzuri/Suzuri/Error/MalformedInput","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput"},{"html_id":"suzuri/Suzuri/Error/TokenExpired","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired"}],"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/DecryptionFailed","path":"Suzuri/Error/DecryptionFailed.html","kind":"class","full_name":"Suzuri::Error::DecryptionFailed","name":"DecryptionFailed","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":94,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/MalformedInput","path":"Suzuri/Error/MalformedInput.html","kind":"class","full_name":"Suzuri::Error::MalformedInput","name":"MalformedInput","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":92,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}},{"html_id":"suzuri/Suzuri/Error/TokenExpired","path":"Suzuri/Error/TokenExpired.html","kind":"class","full_name":"Suzuri::Error::TokenExpired","name":"TokenExpired","abstract":false,"superclass":{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},"ancestors":[{"html_id":"suzuri/Suzuri/Error/DecodeError","kind":"class","full_name":"Suzuri::Error::DecodeError","name":"DecodeError"},{"html_id":"suzuri/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"suzuri/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":93,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri/Error","kind":"module","full_name":"Suzuri::Error","name":"Error"}}]},{"html_id":"suzuri/Suzuri/Token","path":"Suzuri/Token.html","kind":"struct","full_name":"Suzuri::Token","name":"Token","abstract":false,"superclass":{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"suzuri/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"suzuri/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"suzuri/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/suzuri.cr","line_number":97,"url":null}],"repository_name":"suzuri","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"suzuri/Suzuri","kind":"module","full_name":"Suzuri","name":"Suzuri"},"instance_methods":[{"html_id":"payload:Bytes-instance-method","name":"payload","doc":"Returns the decrypted payload as `Bytes`","summary":"Returns the decrypted payload as Bytes
Returns the creation timestamp
","abstract":false,"location":{"filename":"src/suzuri.cr","line_number":106,"url":null},"def":{"name":"timestamp","return_type":"Time","visibility":"Public","body":"@timestamp"}},{"html_id":"to_s:String-instance-method","name":"to_s","doc":"Returns the decrypted payload as `String`","summary":"Returns the decrypted payload as String