- Because Crystal language is missing most OpenSSL bindings (libCrypto, libSSL).
- Of course, Crystal official is always busy, it will not help you solve these problems.
- In despair, I came across openssl.cr, which is a shabby OpenSSL binding.
- This OpenSSL repository was last updated 5 years ago, Fortunately, most of its features are not completely broken.
- So I started to test slowly and repair the broken things, And refer to Ruby prototype for redesign.
- It took one month to fix most of the problems, and finally it was available after three months.
- I think if I was using Rust then I would n’t have encountered these problems.
- But this allows me to learn a lot, I hope it can help more people.
- That's it, Thanks for using, If you encounter any problems, please let me know.
- This is a non-thread safe version, if you need thread safety, use 636f7374 / cherry.cr repository.
- Do not use this repository unless you fully understand manual memory management.
- Improper use is likely to cause the program to crash, If you haven't used it, I suggest you start simple.
-
OpenSSL
- Lib (libCrypto, libSSL)
- There are many bindings in it, many related to loading / reading certificates.
- libCrypto: (I.e.
bio_*
,evp_*
,rsa_*
,dsa_*
,pem_*
,asn1_*
,x509_*
). - libSSL: (I.e.
ssl_ctx_use_certificate
,ssl_ctx_use_privatekey
).
- Asn1 (Integer, Time)
- Integer: Certificate serial number, very useful.
- Time: Certificate validity period, very useful.
- Bio (MemBIO)
- MemBIO: OpenSSL memory buffer, Essential when making Certificate / (Private / Public) keys.
- Nid
- Certificate subject id flag, Essential when making Certificate.
- NID: (I.e.
subject_alt_name
,ext_usage
,usage
).
- Pkey (PKey, DSA, RSA)
- Essential when (create / read) Public / Private Key.
- I encountered a memory leak problem here, it has been fixed.
- SSL (Context, Server, SuperContext, SuperSocket)
- Context: Support loading certificate / private key files from memory (with garbage collection).
- Super*: Slightly complicated but worth it, low memory usage.
- SuperContext: You need to manually free the memory allocation.
- SuperSocket: You need to manually free the memory allocation.
- X509 (ExtensionFactory, Request, SuperCertificate, SuperName).
- ExtensionFactory: Certificate Subject Add / Remove, very important.
- Request: I don't seem to use it, but I also made.
- SuperCertificate: You need to manually free the memory allocation, Generate certificate requires it.
- SuperName: You need to manually free the memory allocation.
- SuperName:
issuer_name
,subject_name
, Generate certificate requires it.
- Lib (libCrypto, libSSL)
-
MITM
- Mitm Slightly complicated but worth it, low memory usage.
- Client: Wrapper for
SuperSocket::Client
. - Server: Wrapper for
SuperSocket::Server
. - Context: Convenient and fast certificate generation, for Man-in-the-middle.
- All of these, You need to manually free the memory allocation.
-
HTTP
- Client
- If you use
SuperContext
asContext
, it will useSuperSocket
. - All of these, You need to manually free the memory allocation.
- If you use
- Client
- This project is currently in WIP (Work In Progress), it may have some undiscovered problems.
- This repository contains OpenSSL and Network components.
- Crystal network components are highly integrated with OpenSSL.
- Why use
Super_*
?- By using
Super_ *
, you can reduce memory usage, You don't want your application to take up too much memory. - But you have to manage the memory manually, please free the memory allocation manually when you don't need it.
- If you free the same memory multiple times, your program will crash.
- When using
Fiber
, please use it withChannel
(It will protect you from free the same memory multiple times).
- By using
Travis-CI
appears to be malfunctioning and this repository cannot be detected.For a better future of the project, I decided to change theMIT
license to theGPLv3
license.
- More specification tests.
- Troubleshooting Deep Memory Errors / Memory Leaks (More stress tests?)
- Remove redundant / irrelevant code (SuperContext, SuperSocket).
- ...
- Simple Mitm Server (Need to be used with Orange.cr)
require "base64"
require "orange"
require "cherry"
# This is a simple design, please do not use it directly.
def handle_client(context, client : Orange::Socket)
return client.close unless request = client.request_payload
STDOUT.puts [client]
case {client.tunnel_mode, client.traffic_type}
when {true, Orange::Traffic::HTTPS}
client = MITM::Server.upgrade client, request, context
buffer = uninitialized UInt8[4096_i32]
length = client.read buffer.to_slice
puts String.new buffer.to_slice[0_i32, length]
end
# But you have to manage the memory manually, please free the memory allocation manually when you don't need it.
# If you free the same memory multiple times, your program will crash.
# When using `Fiber`, please use it with `Channel` (It will protect you from free the same memory multiple times).
client.close
tls_free client
end
def tls_free(socket : IO)
case socket
when Orange::Client
socket = socket.wrapped
end
socket.all_free if socket.responds_to? :all_free
end
# Durian
servers = [] of Tuple(Socket::IPAddress, Durian::Protocol)
servers << Tuple.new Socket::IPAddress.new("8.8.8.8", 53_i32), Durian::Protocol::UDP
servers << Tuple.new Socket::IPAddress.new("1.1.1.1", 53_i32), Durian::Protocol::UDP
resolver = Durian::Resolver.new servers
resolver.ip_cache = Durian::Resolver::Cache::IPAddress.new
# Orange
tcp_server = TCPServer.new "0.0.0.0", 1234_i32
orange = Orange::Server.new tcp_server, resolver
orange.authentication = Orange::Authentication::None
orange.client_timeout = Orange::TimeOut.new
orange.remote_timeout = Orange::TimeOut.new
certificate = Base64.decode_string "Something..."
private_key = Base64.decode_string "Something..."
context = MITM::Context.new certificate, private_key
# Authentication (Optional)
# orange.authentication = Orange::Authentication::Basic
# orange.on_auth = ->(user_name : String, password : String) do
# STDOUT.puts [user_name, password]
# Orange::Verify::Pass
# end
loop do
socket = orange.accept?
spawn do
next unless client = socket
next unless client = orange.process client
handle_client context, client
end
end
-
Simple HTTP Client
- ...
Add this to your application's shard.yml:
dependencies:
cherry:
github: 64726f70/cherry.cr
$ git clone https://github.com/64726f70/cherry.cr.git
$ make test
- Official | Ruby OpenSSL::X509::Certificate
- Official | OpenSSL Documentation
- Official | OpenSSL x509v3_config
- Official | PEM_read_bio_PrivateKey
- Official | X509V3_get_d2i
- Official | Secure programming with the OpenSSL API
- Github | Golang Nid.go
- Github | Rust OpenSSL Password callbacks
- Github | OpenSSL SSL_Rsa.c
- Blogs | The Most Common OpenSSL Commands
- Blogs | OpenSSL – Convert RSA Key to private key
- Blogs | problem with d2i_X509?
- Blogs | Parsing X.509 Certificates with OpenSSL and C
- Blogs | Using the OpenSSL library with macOS Sierra
- StackOverflow | Read certificate files from memory instead of a file using OpenSSL
- StackOverflow | Programmatically Create X509 Certificate using OpenSSL
- StackOverflow | OpenSSL Command to check if a server is presenting a certificate
- StackOverflow | C++ OpenSSL export private key
- StackOverflow | Why is openssl key length different from specified bytes
- StackOverflow | Reading PEM-formatted RSA keyfile with the OpenSSL C API
- StackOverflow | OpenSSL certificate lacks key identifiers
- StackOverflow | OpenSSL CA keyUsage extension
- ...
- #7897 | Need to enhance the OpenSSL::SSL::Context loads Certificate / PrivateKey from Memory
- #7896 | Need to enhance the OpenSSL::X509 more features
- #8108 | openssl ssl_accept sometimes does not return, causes server to hang permanently
- #7291 | Get SNI for OpenSSL
- ...
Name | Creator | Maintainer | Contributor |
---|---|---|---|
64726f70 | √ | √ | |
datanoise | √ |
- MIT License