├── .gitattributes ├── .gitignore ├── .travis.yml ├── Directory.Build.props ├── LICENSE ├── Multiformats.Base.sln ├── NuGet.config ├── README.md ├── appveyor.yml ├── src └── Multiformats.Base │ ├── Base10.cs │ ├── Base16.Lower.cs │ ├── Base16.Upper.cs │ ├── Base16.cs │ ├── Base2.cs │ ├── Base32.HexLower.cs │ ├── Base32.HexPaddedLower.cs │ ├── Base32.HexPaddedUpper.cs │ ├── Base32.HexUpper.cs │ ├── Base32.Lower.cs │ ├── Base32.PaddedLower.cs │ ├── Base32.PaddedUpper.cs │ ├── Base32.Upper.cs │ ├── Base32.Z.cs │ ├── Base32.cs │ ├── Base58.Btc.cs │ ├── Base58.Flickr.cs │ ├── Base58.cs │ ├── Base64.Normal.cs │ ├── Base64.Padded.cs │ ├── Base64.Url.cs │ ├── Base64.UrlPadded.cs │ ├── Base64.cs │ ├── Base8.cs │ ├── Identity.cs │ ├── LetterCasing.cs │ ├── Multibase.cs │ ├── MultibaseEncoding.cs │ └── Multiformats.Base.csproj └── test └── Multiformats.Base.Tests ├── MultibaseTests.cs ├── Multiformats.Base.Tests.csproj ├── test1.csv ├── test2.csv ├── test3.csv ├── test4.csv ├── test5.csv └── test6.csv /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | sudo: required 3 | dist: xenial 4 | mono: latest 5 | dotnet: 2.2.300 6 | os: 7 | - linux 8 | - osx 9 | 10 | notifications: 11 | email: 12 | on_success: change 13 | on_failure: always 14 | 15 | branches: 16 | only: 17 | - master 18 | 19 | cache: 20 | bundler: true 21 | directories: 22 | - ./packages 23 | - /.dotnetcli 24 | - $HOME/.nuget/packages 25 | - $HOME/Library/Caches/Homebrew 26 | 27 | before_install: 28 | - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi 29 | 30 | install: 31 | - git config --global core.autocrlf input 32 | - git submodule update --init --recursive 33 | 34 | script: 35 | - dotnet build -c Release 36 | - dotnet test -c Release -f netcoreapp2.2 --no-build --no-restore --blame 37 | - mono $HOME/.nuget/packages/xunit.runner.console/*/tools/net452/xunit.console.exe ./test/Multiformats.Base.Tests/bin/Release/net461/Multiformats.Base.Tests.dll 38 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | 7 | 8 | /Library/Frameworks/Mono.framework/Versions/Current/lib/mono 9 | /usr/lib/mono 10 | /usr/local/lib/mono 11 | 12 | 13 | $(BaseFrameworkPathOverrideForMono)/4.5-api 14 | $(BaseFrameworkPathOverrideForMono)/4.5.1-api 15 | $(BaseFrameworkPathOverrideForMono)/4.5.2-api 16 | $(BaseFrameworkPathOverrideForMono)/4.6-api 17 | $(BaseFrameworkPathOverrideForMono)/4.6.1-api 18 | $(BaseFrameworkPathOverrideForMono)/4.6.2-api 19 | $(BaseFrameworkPathOverrideForMono)/4.7-api 20 | $(BaseFrameworkPathOverrideForMono)/4.7.1-api 21 | $(BaseFrameworkPathOverrideForMono)/4.7.2-api 22 | true 23 | 24 | 25 | {RawFileName};{CandidateAssemblyFiles};{HintPathFromItem};{TargetFrameworkDirectory};$(FrameworkPathOverride)/Facades;$(AssemblySearchPaths) 26 | $(BaseFrameworkPathOverrideForMono)/4.5;$(BaseFrameworkPathOverrideForMono)/4.5/Facades;$(AssemblySearchPaths) 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/multiformats/cs-multibase/c4d63d8cb16fd7d8653d809cd6c5884e85c5622e/LICENSE -------------------------------------------------------------------------------- /Multiformats.Base.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.27130.2010 4 | MinimumVisualStudioVersion = 15.0.26124.0 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1868BBD8-5963-44BD-B92B-539CF2A79DD2}" 6 | EndProject 7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Multiformats.Base", "src\Multiformats.Base\Multiformats.Base.csproj", "{CB485F6D-C74E-4419-859D-A1623BB62309}" 8 | EndProject 9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{593C0817-7D83-4230-B921-FC1E7F0AFD51}" 10 | EndProject 11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Multiformats.Base.Tests", "test\Multiformats.Base.Tests\Multiformats.Base.Tests.csproj", "{A325E7C4-3F58-4F58-B3DA-395C2928111C}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|Any CPU = Release|Any CPU 19 | Release|x64 = Release|x64 20 | Release|x86 = Release|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Debug|x64.ActiveCfg = Debug|Any CPU 26 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Debug|x64.Build.0 = Debug|Any CPU 27 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Debug|x86.ActiveCfg = Debug|Any CPU 28 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Debug|x86.Build.0 = Debug|Any CPU 29 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Release|x64.ActiveCfg = Release|Any CPU 32 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Release|x64.Build.0 = Release|Any CPU 33 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Release|x86.ActiveCfg = Release|Any CPU 34 | {CB485F6D-C74E-4419-859D-A1623BB62309}.Release|x86.Build.0 = Release|Any CPU 35 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Debug|x64.ActiveCfg = Debug|Any CPU 38 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Debug|x64.Build.0 = Debug|Any CPU 39 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Debug|x86.ActiveCfg = Debug|Any CPU 40 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Debug|x86.Build.0 = Debug|Any CPU 41 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Release|x64.ActiveCfg = Release|Any CPU 44 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Release|x64.Build.0 = Release|Any CPU 45 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Release|x86.ActiveCfg = Release|Any CPU 46 | {A325E7C4-3F58-4F58-B3DA-395C2928111C}.Release|x86.Build.0 = Release|Any CPU 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | GlobalSection(NestedProjects) = preSolution 52 | {CB485F6D-C74E-4419-859D-A1623BB62309} = {1868BBD8-5963-44BD-B92B-539CF2A79DD2} 53 | {A325E7C4-3F58-4F58-B3DA-395C2928111C} = {593C0817-7D83-4230-B921-FC1E7F0AFD51} 54 | EndGlobalSection 55 | GlobalSection(ExtensibilityGlobals) = postSolution 56 | SolutionGuid = {9BA78243-1F7F-41B0-9205-F57DF9577A1D} 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This project is no longer maintained and has been archived.** 2 | 3 | # Multiformats.Base 4 | 5 | [![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats) 6 | [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs) 7 | [![Travis CI](https://img.shields.io/travis/multiformats/cs-multibase.svg?style=flat-square&branch=master)](https://travis-ci.org/multiformats/cs-multibase) 8 | [![AppVeyor](https://img.shields.io/appveyor/ci/tabrath/cs-multihash/master.svg?style=flat-square)](https://ci.appveyor.com/project/tabrath/cs-multibase) 9 | [![NuGet](https://buildstats.info/nuget/Multiformats.Base)](https://www.nuget.org/packages/Multiformats.Base/) 10 | [![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) 11 | [![Codecov](https://img.shields.io/codecov/c/github/multiformats/cs-multibase/master.svg?style=flat-square)](https://codecov.io/gh/multiformats/cs-multibase) 12 | [![Libraries.io](https://img.shields.io/librariesio/github/multiformats/cs-multibase.svg?style=flat-square)](https://libraries.io/github/multiformats/cs-multibase) 13 | 14 | > C# implementation of [multiformats/multibase](https://github.com/multiformats/multibase). 15 | 16 | As stated in the specs, multibase encoded strings are prefixed with an identifier for the base it's encoded in. 17 | 18 | ## Table of Contents 19 | 20 | - [Install](#install) 21 | - [Usage](#usage) 22 | - [Supported base encodings](#supported-base-encodings) 23 | - [Maintainers](#maintainers) 24 | - [Contribute](#contribute) 25 | - [License](#license) 26 | 27 | ## Install 28 | 29 | PM> Install-Package Multiformats.Base 30 | 31 | CLI> dotnet install Multiformats.Base 32 | 33 | ## Usage 34 | ``` csharp 35 | using Multiformats.Base; 36 | using System.Text; 37 | 38 | string encoded = Multibase.Encode(MultibaseEncoding.Base32Lower, Encoding.UTF8.GetBytes("hello world")); 39 | // bnbswy3dpeb3w64tmmq 40 | byte[] decoded = Multibase.Decode(encoded, out MultibaseEncoding encoding); 41 | ``` 42 | 43 | ## Supported base encodings 44 | 45 | * Identity 46 | * Base2 47 | * Base8 48 | * Base10 49 | * Base16 50 | * Base32 51 | * Lower / Upper 52 | * Padded Lower / Upper 53 | * Hex Lower / Upper 54 | * Hex Padded Lower / Upper 55 | * Z-Base32 56 | * Base58 57 | * Bitcoin 58 | * Flickr 59 | * Base64 60 | * Unpadded / Padded 61 | * UrlSafe Unpadded / Padded 62 | 63 | ## Maintainers 64 | 65 | Captain: [@tabrath](https://github.com/tabrath). 66 | 67 | ## Contribute 68 | 69 | Contributions welcome. Please check out [the issues](https://github.com/multiformats/cs-multibase/issues). 70 | 71 | Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). 72 | 73 | Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. 74 | 75 | ## License 76 | 77 | [MIT](LICENSE) © 2018 Trond Bråthen 78 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | PKG_VERSION: 2.0.2 3 | VERSION_SUFFIX: "" 4 | version: ${PKG_VERSION}-{build} 5 | configuration: Release 6 | platform: x64 7 | 8 | skip_commits: 9 | message: /travis/ 10 | files: 11 | - '**\*.md' 12 | - LICENSE 13 | 14 | skip_branch_with_pr: true 15 | 16 | matrix: 17 | fast_finish: true 18 | 19 | init: 20 | - git config --global core.autocrlf input 21 | - ps: $env:BUILD_VERSION = "$env:PKG_VERSION-$env:APPVEYOR_BUILD_NUMBER" 22 | - ps: | 23 | if ($env:APPVEYOR_REPO_BRANCH -eq "master") 24 | { 25 | $env:VERSION_SUFFIX = "" 26 | $env:NUGET_VERSION = "$env:PKG_VERSION" 27 | } 28 | else 29 | { 30 | $env:VERSION_SUFFIX = "beta$env:APPVEYOR_BUILD_NUMBER" 31 | $env:NUGET_VERSION = "$env:PKG_VERSION-$env:VERSION_SUFFIX" 32 | } 33 | - ps: Update-AppveyorBuild -Version $env:BUILD_VERSION 34 | - ps: Write-Host "Build version $env:BUILD_VERSION, NuGet version $env:NUGET_VERSION, Version suffix $env:VERSION_SUFFIX" 35 | 36 | install: 37 | - git submodule update --init --recursive 38 | 39 | build_script: 40 | - ps: | 41 | if ($env:APPVEYOR_REPO_BRANCH -eq "master") 42 | { 43 | dotnet build -c $env:CONFIGURATION 44 | } 45 | else 46 | { 47 | dotnet build -c $env:CONFIGURATION --version-suffix $env:VERSION_SUFFIX 48 | } 49 | 50 | test: off 51 | 52 | test_script: 53 | - dotnet test -c %CONFIGURATION% -f netcoreapp2.2 /p:CollectCoverage=true %APPVEYOR_BUILD_FOLDER%\test\Multiformats.Base.Tests 54 | 55 | on_success: 56 | - choco install codecov 57 | - codecov -f "%APPVEYOR_BUILD_FOLDER%\test\Multiformats.Base.Tests\coverage.opencover.xml" 58 | 59 | artifacts: 60 | - path: '**\*.nupkg' 61 | name: nupkg 62 | - path: '**\*.snupkg' 63 | name: snupkg 64 | 65 | cache: 66 | - '%USERPROFILE%\.local' 67 | - '%USERPROFILE%\.nuget\packages -> **\*.csproj' 68 | - '%LocalAppData%\NuGet\Cache' 69 | - '%LocalAppData%\Python' 70 | - '.\packages -> **\project.json' 71 | - '.\tools' 72 | - '\Python34' 73 | 74 | nuget: 75 | account_feed: true 76 | 77 | deploy: 78 | - provider: NuGet 79 | api_key: 80 | secure: WcDqU36pLPvA+s5D4N0VEsi7AZGewvf4croE/D3rh3F+iqiztq9w5gHbrhgoTNS9 81 | on: 82 | branch: master 83 | appveyor_repo_tag: true 84 | - provider: GitHub 85 | description: 'Release description' 86 | auth_token: 87 | secure: nsZHZ5nFBFP4fZoVUEeWeZKx7LUASVqCZ+JblTox+02RfTAOlANdFWeCqOwhu7pk 88 | artifact: /.*\.nupkg/ # upload all NuGet packages to release assets 89 | draft: false 90 | prerelease: false 91 | on: 92 | branch: master # release from master branch only 93 | appveyor_repo_tag: true 94 | -------------------------------------------------------------------------------- /src/Multiformats.Base/Base10.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Numerics; 5 | 6 | namespace Multiformats.Base 7 | { 8 | internal class Base10 : Multibase 9 | { 10 | private static readonly char[] _alphabet = "0123456789".ToCharArray(); 11 | 12 | protected override string Name => "base10"; 13 | protected override char Prefix => '9'; 14 | protected override char[] Alphabet => _alphabet; 15 | 16 | public override byte[] Decode(string input) 17 | { 18 | var big = BigInteger.Parse("00" + input, NumberStyles.None); 19 | return LeadingZeros(input).Concat(big.ToByteArray().Reverse().SkipWhile(b => b == 0)).ToArray(); 20 | } 21 | 22 | private static IEnumerable LeadingZeros(IEnumerable input) 23 | { 24 | return Enumerable.Range(0, input.TakeWhile(b => b == '0').Count()).Select(_ => (byte)0x00); 25 | } 26 | 27 | private static IEnumerable LeadingNulls(IEnumerable input) 28 | { 29 | return Enumerable.Range(0, input.TakeWhile(b => b == 0x00).Count()).Select(_ => '0'); 30 | } 31 | 32 | public override string Encode(byte[] bytes) 33 | { 34 | var big = new BigInteger(bytes.Reverse().Concat(new byte[]{0x00}).ToArray()); 35 | return new string(LeadingNulls(bytes).ToArray()) + big.ToString(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Multiformats.Base/Base16.Lower.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base16Lower : Base16 4 | { 5 | private static readonly char[] _alphabet = "0123456789abcdef".ToCharArray(); 6 | 7 | protected override string Name => "base16"; 8 | protected override char Prefix => 'f'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, LetterCasing.Lower); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, LetterCasing.Lower); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base16.Upper.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base16Upper : Base16 4 | { 5 | private static readonly char[] _alphabet = "0123456789ABCDEF".ToCharArray(); 6 | 7 | protected override string Name => "BASE16"; 8 | protected override char Prefix => 'F'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, LetterCasing.Upper); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, LetterCasing.Upper); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base16.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace Multiformats.Base 6 | { 7 | internal abstract class Base16 : Multibase 8 | { 9 | protected byte[] Decode(string input, LetterCasing casing) 10 | { 11 | if (casing == LetterCasing.Lower && input.Any(char.IsUpper)) 12 | input = input.ToLower(); 13 | 14 | if (casing == LetterCasing.Upper && input.Any(char.IsLower)) 15 | input = input.ToUpper(); 16 | 17 | return Enumerable.Range(0, input.Length / 2) 18 | .Select(i => (byte)Convert.ToInt32(input.Substring(i * 2, 2), 16)) 19 | .ToArray(); 20 | } 21 | 22 | protected string Encode(byte[] input, LetterCasing casing) 23 | { 24 | var format = casing == LetterCasing.Lower ? "{0:x2}" : "{0:X2}"; 25 | 26 | return input.Aggregate(new StringBuilder(), (sb, b) => sb.AppendFormat(format, b)).ToString(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base2.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace Multiformats.Base 4 | { 5 | internal class Base2 : Multibase 6 | { 7 | private static readonly char[] _alphabet = { '0', '1' }; 8 | 9 | protected override string Name => "base2"; 10 | protected override char Prefix => '0'; 11 | protected override char[] Alphabet => _alphabet; 12 | 13 | public override byte[] Decode(string input) 14 | { 15 | var bytes = new byte[input.Length / 8]; 16 | for (var index = 0; index < input.Length / 8; index++) 17 | { 18 | for (var i = 0; i < 8; i++) 19 | if (input[(index * 8) + i] == '1') 20 | bytes[index] |= (byte)(1 << (7 - i)); 21 | } 22 | 23 | return bytes; 24 | } 25 | 26 | public override string Encode(byte[] bytes) => new string(bytes.Select(b => Enumerable.Range(0, 8).Select(i => (b & (1 << i)) != 0 ? '1' : '0').Reverse()).SelectMany(b => b).ToArray()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.HexLower.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32HexLower : Base32 4 | { 5 | private static readonly char[] _alphabet = "0123456789abcdefghijklmnopqrstuv".ToCharArray(); 6 | 7 | protected override string Name => "base32hex"; 8 | protected override char Prefix => 'v'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, LetterCasing.Lower); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.HexPaddedLower.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32HexPaddedLower : Base32 4 | { 5 | private static readonly char[] _alphabet = "0123456789abcdefghijklmnopqrstuv=".ToCharArray(); 6 | 7 | protected override string Name => "base32hexpad"; 8 | protected override char Prefix => 't'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, true, LetterCasing.Lower); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, true); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.HexPaddedUpper.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32HexPaddedUpper : Base32 4 | { 5 | private static readonly char[] _alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUV=".ToCharArray(); 6 | 7 | protected override string Name => "BASE32HEXPAD"; 8 | protected override char Prefix => 'T'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, true, LetterCasing.Upper); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, true); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.HexUpper.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32HexUpper : Base32 4 | { 5 | private static readonly char[] _alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUV".ToCharArray(); 6 | 7 | protected override string Name => "BASE32HEX"; 8 | protected override char Prefix => 'V'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, LetterCasing.Upper); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.Lower.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32Lower : Base32 4 | { 5 | private static readonly char[] _alphabet = "abcdefghijklmnopqrstuvwxyz234567".ToCharArray(); 6 | 7 | protected override string Name => "base32"; 8 | protected override char Prefix => 'b'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, LetterCasing.Lower); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.PaddedLower.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32PaddedLower : Base32 4 | { 5 | private static readonly char[] _alphabet = "abcdefghijklmnopqrstuvwxyz234567=".ToCharArray(); 6 | 7 | protected override string Name => "base32pad"; 8 | protected override char Prefix => 'c'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, true, LetterCasing.Lower); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, true); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.PaddedUpper.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32PaddedUpper : Base32 4 | { 5 | private static readonly char[] _alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=".ToCharArray(); 6 | 7 | protected override string Name => "BASE32PAD"; 8 | protected override char Prefix => 'C'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, true, LetterCasing.Upper); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, true); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.Upper.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32Upper : Base32 4 | { 5 | private static readonly char[] _alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".ToCharArray(); 6 | 7 | protected override string Name => "BASE32"; 8 | protected override char Prefix => 'B'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, LetterCasing.Upper); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.Z.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base32Z : Base32 4 | { 5 | private static readonly char[] _alphabet = "ybndrfg8ejkmcpqxot1uwisza345h769".ToCharArray(); 6 | 7 | protected override string Name => "base32z"; 8 | protected override char Prefix => 'h'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, LetterCasing.Ignore); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Multiformats.Base 5 | { 6 | internal abstract class Base32 : Multibase 7 | { 8 | protected byte[] Decode(string input, bool padding, LetterCasing casing) 9 | { 10 | if (padding) 11 | input = input.TrimEnd('='); 12 | 13 | if (casing == LetterCasing.Lower && input.Any(char.IsUpper)) 14 | input = input.ToLower(); 15 | 16 | if (casing == LetterCasing.Upper && input.Any(char.IsLower)) 17 | input = input.ToUpper(); 18 | 19 | var bits = 0; 20 | var value = 0; 21 | var index = 0; 22 | var output = new byte[(input.Length * 5 / 8) | 0]; 23 | 24 | for (var i = 0; i < input.Length; i++) 25 | { 26 | value = (value << 5) | Array.IndexOf(Alphabet, input[i]); 27 | bits += 5; 28 | 29 | if (bits >= 8) 30 | { 31 | output[index++] = (byte)(((uint)value >> (bits - 8)) & 255); 32 | bits -= 8; 33 | } 34 | } 35 | 36 | return output; 37 | } 38 | 39 | protected string Encode(byte[] bytes, bool padding) 40 | { 41 | int bits = 0; 42 | int value = 0; 43 | string output = ""; 44 | 45 | for (var i = 0; i < bytes.Length; i++) 46 | { 47 | value = (value << 8) | bytes[i]; 48 | bits += 8; 49 | 50 | while (bits >= 5) 51 | { 52 | output += Alphabet[(int)((uint)value >> (bits - 5)) & 31]; 53 | bits -= 5; 54 | } 55 | } 56 | 57 | if (bits > 0) 58 | output += Alphabet[(value << (5 - bits)) & 31]; 59 | 60 | if (padding) 61 | { 62 | while ((output.Length % 8) != 0) 63 | output += '='; 64 | } 65 | 66 | return output; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Multiformats.Base/Base58.Btc.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base58Btc : Base58 4 | { 5 | private static readonly char[] _alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".ToCharArray(); 6 | 7 | protected override string Name => "base58btc"; 8 | protected override char Prefix => 'z'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, _alphabet); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, _alphabet); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base58.Flickr.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base58Flickr : Base58 4 | { 5 | private static readonly char[] _alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ".ToCharArray(); 6 | 7 | protected override string Name => "base58flickr"; 8 | protected override char Prefix => 'Z'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, _alphabet); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, _alphabet); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base58.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Numerics; 5 | 6 | namespace Multiformats.Base 7 | { 8 | internal abstract class Base58 : Multibase 9 | { 10 | protected string Encode(byte[] b, char[] alphabet) 11 | { 12 | return new string( 13 | b.TakeWhile(c => c == 0) 14 | .Select(_ => alphabet[0]) 15 | .Concat(ParseBigInt(b.Aggregate(0, (current, t) => current * 256 + t), alphabet).Reverse()) 16 | .ToArray()); 17 | } 18 | 19 | private static IEnumerable ParseBigInt(BigInteger intData, char[] alphabet) 20 | { 21 | var len = alphabet.Length; 22 | while (intData > 0) 23 | { 24 | var rem = (int)(intData % len); 25 | intData /= len; 26 | yield return alphabet[rem]; 27 | } 28 | } 29 | 30 | private static readonly ConcurrentDictionary DecodeMap = new ConcurrentDictionary(); 31 | 32 | private static byte[] CreateDecodeMap(char[] alphabet) 33 | { 34 | var map = Enumerable.Range(0, 256).Select(b => (byte)0xFF).ToArray(); 35 | for (var i = 0; i < alphabet.Length; i++) 36 | map[alphabet[i]] = (byte)i; 37 | return map; 38 | } 39 | 40 | protected byte[] Decode(string b, char[] alphabet) 41 | { 42 | lock (DecodeMap) 43 | { 44 | var decodeMap = DecodeMap.GetOrAdd(alphabet, CreateDecodeMap); 45 | var len = alphabet.Length; 46 | 47 | return b.TakeWhile(c => c == alphabet[0]) 48 | .Select(_ => (byte)0) 49 | .Concat(b.Select(c => decodeMap[c]) 50 | .Aggregate(0, (current, c) => current * len + c) 51 | .ToByteArray() 52 | .Reverse() 53 | .SkipWhile(c => c == 0)) 54 | .ToArray(); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Multiformats.Base/Base64.Normal.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base64Normal : Base64 4 | { 5 | private static readonly char[] _alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".ToCharArray(); 6 | 7 | protected override string Name => "base64"; 8 | protected override char Prefix => 'm'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, false); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false, false); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Multiformats.Base/Base64.Padded.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base64Padded : Base64 4 | { 5 | private static readonly char[] _alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".ToCharArray(); 6 | 7 | protected override string Name => "base64pad"; 8 | protected override char Prefix => 'M'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, false, true); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, false, true); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base64.Url.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base64Url : Base64 4 | { 5 | private static readonly char[] _alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".ToCharArray(); 6 | 7 | protected override string Name => "base64url"; 8 | protected override char Prefix => 'u'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, true, false); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, true, false); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base64.UrlPadded.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal class Base64UrlPadded : Base64 4 | { 5 | private static readonly char[] _alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=".ToCharArray(); 6 | 7 | protected override string Name => "base64urlpad"; 8 | protected override char Prefix => 'U'; 9 | protected override char[] Alphabet => _alphabet; 10 | 11 | public override byte[] Decode(string input) => Decode(input, true, true); 12 | 13 | public override string Encode(byte[] bytes) => Encode(bytes, true, true); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base64.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Multiformats.Base 4 | { 5 | internal abstract class Base64 : Multibase 6 | { 7 | private static string Pad(string input) 8 | { 9 | var diff = input.Length % 4; 10 | 11 | return diff > 0 ? input + new string('=', 4 - diff) : input; 12 | } 13 | 14 | protected string Encode(byte[] input, bool urlSafe, bool padded) 15 | { 16 | var result = Convert.ToBase64String(input); 17 | if (urlSafe) 18 | result = result.Replace('+', '-').Replace('/', '_'); 19 | 20 | if (!padded) 21 | result = result.TrimEnd('='); 22 | 23 | return result; 24 | } 25 | 26 | protected byte[] Decode(string input, bool urlSafe, bool padded) 27 | { 28 | if (urlSafe) 29 | input = input.Replace('-', '+').Replace('_', '/'); 30 | 31 | input = Pad(input.TrimEnd('=')); 32 | 33 | return Convert.FromBase64String(input); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Base8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Multiformats.Base 6 | { 7 | internal class Base8 : Multibase 8 | { 9 | private static readonly char[] _alphabet = {'0', '1', '2', '3', '4', '5', '6', '7'}; 10 | 11 | protected override string Name => "base8"; 12 | protected override char Prefix => '7'; 13 | protected override char[] Alphabet => _alphabet; 14 | 15 | private static byte[] FromOct(byte o) => new[] { (byte)(o >> 2), (byte)((o >> 1) & 1), (byte)(o & 1) }; 16 | private static byte ToNum8(char c) => Convert.ToByte($"{c}", 8); 17 | private static char FromBit(byte b) => b == 0 ? '0' : '1'; 18 | 19 | public override byte[] Decode(string input) 20 | { 21 | var base2 = _bases[MultibaseEncoding.Base2]; 22 | 23 | var bin = input.Select(ToNum8).SelectMany(FromOct).Select(FromBit); 24 | 25 | var modlen = input.Length % 8; 26 | 27 | var binstr = ""; 28 | if (modlen == 0) 29 | binstr = new string(bin.ToArray()); 30 | else if (modlen == 3) 31 | binstr = new string(bin.Skip(1).ToArray()); 32 | else if (modlen == 6) 33 | binstr = new string(bin.Skip(2).ToArray()); 34 | 35 | return base2.Decode(binstr); 36 | } 37 | 38 | private static byte ToBit(char c) => c == '0' ? (byte)0 : (byte)1; 39 | private static byte ToOct(IEnumerable b) 40 | { 41 | var bin = b.ToArray(); 42 | 43 | return (byte)((bin[0] << 2) | (bin[1] << 1) | bin[2]); 44 | } 45 | private static char FromNum8(byte b) => Convert.ToString(b, 8).First(); 46 | 47 | private static IEnumerable BinToOct(IEnumerable b) 48 | { 49 | var result = new List(); 50 | var batch = new List(); 51 | foreach (var x in b) 52 | { 53 | batch.Add(x); 54 | 55 | if (batch.Count == 3) 56 | { 57 | result.Add(ToOct(batch)); 58 | batch.Clear(); 59 | } 60 | } 61 | 62 | return result; 63 | } 64 | 65 | public override string Encode(byte[] bytes) 66 | { 67 | var base2 = _bases[MultibaseEncoding.Base2]; 68 | var encoded = base2.Encode(bytes); 69 | var modlen = encoded.Length % 3; 70 | var prepad = new string('0', modlen == 0 ? 0 : 3 - modlen); 71 | 72 | return new string(BinToOct((prepad + encoded).Select(ToBit)).Select(FromNum8).ToArray()); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Identity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Multiformats.Base 5 | { 6 | internal class Identity : Multibase 7 | { 8 | protected override string Name => "identity"; 9 | protected override char Prefix => '\0'; 10 | protected override char[] Alphabet => Array.Empty(); 11 | 12 | protected override bool IsValid(string value) => true; 13 | public override byte[] Decode(string input) => input.Select(Convert.ToByte).ToArray(); 14 | public override string Encode(byte[] bytes) => new string(bytes.Select(Convert.ToChar).ToArray()); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/LetterCasing.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | internal enum LetterCasing 4 | { 5 | Ignore, 6 | Lower, 7 | Upper 8 | } 9 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Multibase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Multiformats.Base 6 | { 7 | public abstract class Multibase 8 | { 9 | protected static readonly Dictionary _bases; 10 | 11 | static Multibase() 12 | { 13 | _bases = new Dictionary 14 | { 15 | {MultibaseEncoding.Identity, new Identity()}, 16 | {MultibaseEncoding.Base2, new Base2()}, 17 | {MultibaseEncoding.Base8, new Base8()}, 18 | {MultibaseEncoding.Base10, new Base10()}, 19 | {MultibaseEncoding.Base16Lower, new Base16Lower()}, 20 | {MultibaseEncoding.Base16Upper, new Base16Upper()}, 21 | {MultibaseEncoding.Base32Lower, new Base32Lower()}, 22 | {MultibaseEncoding.Base32Upper, new Base32Upper()}, 23 | {MultibaseEncoding.Base32PaddedLower, new Base32PaddedLower()}, 24 | {MultibaseEncoding.Base32PaddedUpper, new Base32PaddedUpper()}, 25 | {MultibaseEncoding.Base32HexLower, new Base32HexLower()}, 26 | {MultibaseEncoding.Base32HexUpper, new Base32HexUpper()}, 27 | {MultibaseEncoding.Base32HexPaddedLower, new Base32HexPaddedLower()}, 28 | {MultibaseEncoding.Base32HexPaddedUpper, new Base32HexPaddedUpper()}, 29 | {MultibaseEncoding.Base32Z, new Base32Z()}, 30 | {MultibaseEncoding.Base58Btc, new Base58Btc()}, 31 | {MultibaseEncoding.Base58Flickr, new Base58Flickr()}, 32 | {MultibaseEncoding.Base64, new Base64Normal()}, 33 | {MultibaseEncoding.Base64Padded, new Base64Padded()}, 34 | {MultibaseEncoding.Base64Url, new Base64Url()}, 35 | {MultibaseEncoding.Base64UrlPadded, new Base64UrlPadded()}, 36 | }; 37 | } 38 | 39 | public static Multibase Base2 => _bases[MultibaseEncoding.Base2]; 40 | public static Multibase Base8 => _bases[MultibaseEncoding.Base8]; 41 | public static Multibase Base10 => _bases[MultibaseEncoding.Base10]; 42 | public static Multibase Base16 => _bases[MultibaseEncoding.Base16Lower]; 43 | public static Multibase Base32 => _bases[MultibaseEncoding.Base32Lower]; 44 | public static Multibase Base58 => _bases[MultibaseEncoding.Base58Btc]; 45 | public static Multibase Base64 => _bases[MultibaseEncoding.Base64]; 46 | 47 | protected abstract string Name { get; } 48 | protected abstract char Prefix { get; } 49 | protected abstract char[] Alphabet { get; } 50 | protected virtual bool IsValid(string value) => value.Distinct().All(c => Array.IndexOf(Alphabet, c) > -1); 51 | 52 | public abstract byte[] Decode(string input); 53 | public abstract string Encode(byte[] bytes); 54 | 55 | /// 56 | /// Encode a byte array to multibase given encoding. 57 | /// 58 | /// Encoding 59 | /// Bytes 60 | /// Encoded string 61 | public static string Encode(MultibaseEncoding encoding, byte[] bytes) 62 | { 63 | if (!_bases.TryGetValue(encoding, out var @base)) 64 | throw new NotSupportedException($"{encoding} is not supported."); 65 | 66 | return Encode(@base, bytes, true); 67 | } 68 | 69 | /// 70 | /// Encode a byte array to multibase given encoding in string format. 71 | /// 72 | /// Encoding 73 | /// Bytes 74 | /// Encoded string 75 | public static string Encode(string encoding, byte[] bytes) 76 | { 77 | var @base = _bases.Values.SingleOrDefault(b => b.Name.Equals(encoding)); 78 | if (@base == null) 79 | throw new NotSupportedException($"{encoding} is not supported."); 80 | 81 | return Encode(@base, bytes, true); 82 | } 83 | 84 | private static string Encode(Multibase @base, byte[] bytes, bool prefix) 85 | { 86 | if (bytes == null || bytes.Length == 0) 87 | throw new ArgumentNullException(nameof(bytes)); 88 | 89 | return prefix ? @base.Prefix + @base.Encode(bytes) : @base.Encode(bytes); 90 | } 91 | 92 | /// 93 | /// Encode a byte array given encoding (without multibase prefix). 94 | /// 95 | /// Encoding 96 | /// Bytes 97 | /// Encoded string 98 | public static string EncodeRaw(MultibaseEncoding encoding, byte[] bytes) 99 | { 100 | var @base = _bases[encoding]; 101 | if (@base == null) 102 | throw new NotSupportedException($"{encoding} is not supported."); 103 | 104 | return Encode(@base, bytes, false); 105 | } 106 | 107 | /// 108 | /// Decode an multibase encoded string. 109 | /// 110 | /// Encoded string 111 | /// Encoding used 112 | /// Don't allow non-valid characters for given encoding 113 | /// Bytes 114 | public static byte[] Decode(string input, out MultibaseEncoding encoding, bool strict = true) 115 | { 116 | if (string.IsNullOrEmpty(input)) 117 | throw new ArgumentNullException(nameof(input)); 118 | 119 | var @base = _bases.Values.SingleOrDefault(b => b.Prefix == input[0]); 120 | if (@base == null) 121 | throw new NotSupportedException($"{input[0]} is an unknown encoding prefix."); 122 | 123 | var value = input.Substring(1); 124 | encoding = _bases.SingleOrDefault(kv => kv.Value.Equals(@base)).Key; 125 | 126 | if (strict && !@base.IsValid(value)) 127 | throw new InvalidOperationException($"{value} contains invalid chars for {encoding}."); 128 | 129 | return @base.Decode(value); 130 | } 131 | 132 | /// 133 | /// Decode an multibase encoded string. 134 | /// 135 | /// Encoded string 136 | /// Encoding used 137 | /// Don't allow non-valid characters for given encoding 138 | /// Bytes 139 | public static byte[] Decode(string input, out string encoding, bool strict = true) 140 | { 141 | if (string.IsNullOrEmpty(input)) 142 | throw new ArgumentNullException(nameof(input)); 143 | 144 | var @base = _bases.Values.SingleOrDefault(b => b.Prefix == input[0]); 145 | if (@base == null) 146 | throw new NotSupportedException($"{input[0]} is an unknown encoding prefix."); 147 | 148 | var value = input.Substring(1); 149 | encoding = @base.Name; 150 | 151 | if (strict && !@base.IsValid(value)) 152 | throw new InvalidOperationException($"{value} contains invalid chars for {encoding}."); 153 | 154 | return @base.Decode(value); 155 | } 156 | 157 | /// 158 | /// Decode an encoded string using given encoded (without multibase prefix). 159 | /// 160 | /// Encoding 161 | /// Encoded string 162 | /// Bytes 163 | public static byte[] DecodeRaw(MultibaseEncoding encoding, string input) 164 | { 165 | if (string.IsNullOrEmpty(input)) 166 | throw new ArgumentNullException(nameof(input)); 167 | 168 | if (!_bases.TryGetValue(encoding, out var @base)) 169 | throw new NotSupportedException($"{encoding} is an unknown encoding."); 170 | 171 | return @base.Decode(input); 172 | } 173 | 174 | /// 175 | /// Try to decode an encoded string. If prefixed with a multibase prefix it's guaranteed to give the correct value, if not there's no guarantee it will pick the right encoding. 176 | /// 177 | /// Encoded string 178 | /// Guessed encoding 179 | /// Decoded bytes 180 | /// True on success (no guarantee it's correct), false on error 181 | public static bool TryDecode(string input, out MultibaseEncoding encoding, out byte[] bytes) 182 | { 183 | try 184 | { 185 | // special case for base2 without prefix 186 | if (input[0] == '0' && input.Length % 8 == 0) 187 | throw new Exception(); 188 | 189 | bytes = Decode(input, out encoding); 190 | return true; 191 | } 192 | catch 193 | { 194 | foreach (var @base in _bases.Values.Skip(1).Where(b => b.IsValid(input))) 195 | { 196 | try 197 | { 198 | bytes = @base.Decode(input); 199 | encoding = _bases.SingleOrDefault(kv => kv.Value.Equals(@base)).Key; 200 | return true; 201 | } 202 | catch 203 | { 204 | } 205 | } 206 | } 207 | 208 | encoding = default(MultibaseEncoding); 209 | bytes = null; 210 | return false; 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/Multiformats.Base/MultibaseEncoding.cs: -------------------------------------------------------------------------------- 1 | namespace Multiformats.Base 2 | { 3 | public enum MultibaseEncoding 4 | { 5 | Identity, 6 | Base2, 7 | Base8, 8 | Base10, 9 | Base16Lower, 10 | Base16Upper, 11 | Base32Lower, 12 | Base32Upper, 13 | Base32PaddedLower, 14 | Base32PaddedUpper, 15 | Base32Z, 16 | Base32HexLower, 17 | Base32HexUpper, 18 | Base32HexPaddedLower, 19 | Base32HexPaddedUpper, 20 | Base58Btc, 21 | Base58Flickr, 22 | Base64, 23 | Base64Padded, 24 | Base64Url, 25 | Base64UrlPadded 26 | } 27 | } -------------------------------------------------------------------------------- /src/Multiformats.Base/Multiformats.Base.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Multiformat base encodings 5 | Copyright © tabrath 2018 6 | Multiformats.Base 7 | 2.0.2 8 | tabrath 9 | net461;netstandard1.6;netstandard2.0; 10 | true 11 | Multiformats.Base 12 | Multiformats.Base 13 | multiformats multibase base2 base8 base10 base16 base32 base58 base64 z-base32 14 | https://cdn.rawgit.com/multiformats/website/116894f6/favicon.png 15 | https://github.com/multiformats/cs-multibase/blob/master/LICENSE 16 | git 17 | https://github.com/multiformats/cs-multibase 18 | $(PackageTargetFallback);netstandard;portable-net461+win8 19 | 1.6.1 20 | true 21 | 22 | 23 | 24 | true 25 | portable 26 | false 27 | $(DefineConstants);DEBUG 28 | 29 | 30 | portable 31 | true 32 | $(DefineConstants) 33 | 34 | 35 | 36 | 37 | true 38 | 39 | false 40 | 41 | true 42 | snupkg 43 | .pdb;$(AllowedOutputExtensionsInPackageBuildOutputFolder) 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | all 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/MultibaseTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | using Xunit.Sdk; 10 | 11 | namespace Multiformats.Base.Tests 12 | { 13 | public class MultibaseTests 14 | { 15 | [Fact] 16 | public void Decode_GivenInvalidChars_ThrowsInvalidOperationException() 17 | { 18 | // prefix 0 - base2 19 | // value 99 - invalid chars 20 | 21 | Assert.Throws(() => Multibase.Decode("099", out string _)); 22 | } 23 | 24 | [Theory] 25 | [InlineData("")] 26 | [InlineData(null)] 27 | public void Decode_GivenEmptyInput_ThrowsArgumentNullException(string value) 28 | { 29 | Assert.Throws(() => Multibase.Decode(value, out string _)); 30 | } 31 | 32 | [Fact] 33 | public void Decode_GivenUnknownPrefix_ThrowsUnsupportedException() 34 | { 35 | Assert.Throws(() => Multibase.Decode("ø", out string _)); 36 | } 37 | 38 | [Fact] 39 | public void DecodeRaw_GivenUnknownEncoding_ThrowsUnsupportedException() 40 | { 41 | Assert.Throws(() => Multibase.DecodeRaw((MultibaseEncoding)0x2000, "abab")); 42 | } 43 | 44 | [Theory] 45 | [InlineData("")] 46 | [InlineData(null)] 47 | public void DecodeRaw_GivenEmptyInput_ThrowsArgumentNullException(string value) 48 | { 49 | Assert.Throws(() => Multibase.DecodeRaw(MultibaseEncoding.Identity, value)); 50 | } 51 | 52 | [Fact] 53 | public void Encode_GivenEmptyBytes_ThrowsArgumentNullException() 54 | { 55 | Assert.Throws(() => Multibase.Encode(MultibaseEncoding.Base2, new byte[] { })); 56 | } 57 | 58 | [Fact] 59 | public void Encode_GivenNullBytes_ThrowsArgumentNullException() 60 | { 61 | Assert.Throws(() => Multibase.Encode(MultibaseEncoding.Base2, null)); 62 | } 63 | 64 | [Fact] 65 | public void Encode_GivenUnknownEncoding_ThrowsUnsupportedException() 66 | { 67 | Assert.Throws(() => Multibase.Encode((MultibaseEncoding)0x2000, new byte[] { 0, 1, 2, 3 })); 68 | } 69 | 70 | [Theory] 71 | [InlineData(MultibaseEncoding.Identity)] 72 | [InlineData(MultibaseEncoding.Base2)] 73 | [InlineData(MultibaseEncoding.Base8)] 74 | [InlineData(MultibaseEncoding.Base10)] 75 | [InlineData(MultibaseEncoding.Base16Lower)] 76 | [InlineData(MultibaseEncoding.Base16Upper)] 77 | [InlineData(MultibaseEncoding.Base32Lower)] 78 | [InlineData(MultibaseEncoding.Base32Upper)] 79 | [InlineData(MultibaseEncoding.Base32PaddedLower)] 80 | [InlineData(MultibaseEncoding.Base32PaddedUpper)] 81 | [InlineData(MultibaseEncoding.Base32HexLower)] 82 | [InlineData(MultibaseEncoding.Base32HexUpper)] 83 | [InlineData(MultibaseEncoding.Base32HexPaddedLower)] 84 | [InlineData(MultibaseEncoding.Base32HexPaddedUpper)] 85 | [InlineData(MultibaseEncoding.Base58Btc)] 86 | [InlineData(MultibaseEncoding.Base58Flickr)] 87 | [InlineData(MultibaseEncoding.Base64)] 88 | [InlineData(MultibaseEncoding.Base64Padded)] 89 | [InlineData(MultibaseEncoding.Base64Url)] 90 | [InlineData(MultibaseEncoding.Base64UrlPadded)] 91 | public void TestRoundTrip(MultibaseEncoding encoding) 92 | { 93 | var rand = new Random(Environment.TickCount); 94 | var buf = new byte[rand.Next(16, 256)]; 95 | rand.NextBytes(buf); 96 | 97 | var encoded = Multibase.EncodeRaw(encoding, buf); 98 | var decoded = Multibase.DecodeRaw(encoding, encoded); 99 | 100 | Assert.Equal(decoded, buf); 101 | } 102 | 103 | [Theory] 104 | [InlineData(MultibaseEncoding.Identity)] 105 | [InlineData(MultibaseEncoding.Base2)] 106 | [InlineData(MultibaseEncoding.Base8)] 107 | [InlineData(MultibaseEncoding.Base10)] 108 | [InlineData(MultibaseEncoding.Base16Lower)] 109 | [InlineData(MultibaseEncoding.Base16Upper)] 110 | [InlineData(MultibaseEncoding.Base32Lower)] 111 | [InlineData(MultibaseEncoding.Base32Upper)] 112 | [InlineData(MultibaseEncoding.Base32PaddedLower)] 113 | [InlineData(MultibaseEncoding.Base32PaddedUpper)] 114 | [InlineData(MultibaseEncoding.Base32HexLower)] 115 | [InlineData(MultibaseEncoding.Base32HexUpper)] 116 | [InlineData(MultibaseEncoding.Base32HexPaddedLower)] 117 | [InlineData(MultibaseEncoding.Base32HexPaddedUpper)] 118 | [InlineData(MultibaseEncoding.Base58Btc)] 119 | [InlineData(MultibaseEncoding.Base58Flickr)] 120 | [InlineData(MultibaseEncoding.Base64)] 121 | [InlineData(MultibaseEncoding.Base64Padded)] 122 | [InlineData(MultibaseEncoding.Base64Url)] 123 | [InlineData(MultibaseEncoding.Base64UrlPadded)] 124 | public void TestRoundTripRaw(MultibaseEncoding encoding) 125 | { 126 | var rand = new Random(Environment.TickCount); 127 | var buf = new byte[rand.Next(16, 256)]; 128 | rand.NextBytes(buf); 129 | 130 | var encoded = Multibase.Encode(encoding, buf); 131 | var decoded = Multibase.Decode(encoded, out MultibaseEncoding decodedEncoding); 132 | 133 | Assert.Equal(encoding, decodedEncoding); 134 | Assert.Equal(decoded, buf); 135 | } 136 | 137 | [Theory] 138 | [InlineData("001000100011001010110001101100101011011100111010001110010011000010110110001101001011110100110010100100000011001010111011001100101011100100111100101110100011010000110100101101110011001110010000100100001", MultibaseEncoding.Base2)] 139 | [InlineData("71043126154533472162302661513646244031273145344745643206455631620441", MultibaseEncoding.Base8)] 140 | [InlineData("f446563656e7472616c697a652065766572797468696e672121", MultibaseEncoding.Base16Lower)] 141 | [InlineData("F446563656E7472616C697A652065766572797468696E672121", MultibaseEncoding.Base16Upper)] 142 | [InlineData("birswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb", MultibaseEncoding.Base32Lower)] 143 | [InlineData("BIRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJB", MultibaseEncoding.Base32Upper)] 144 | [InlineData("v8him6pbeehp62r39f9ii0pbmclp7it38d5n6e891", MultibaseEncoding.Base32HexLower)] 145 | [InlineData("V8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E891", MultibaseEncoding.Base32HexUpper)] 146 | [InlineData("cirswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb", MultibaseEncoding.Base32PaddedLower)] 147 | [InlineData("CIRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJB", MultibaseEncoding.Base32PaddedUpper)] 148 | [InlineData("t8him6pbeehp62r39f9ii0pbmclp7it38d5n6e891", MultibaseEncoding.Base32HexPaddedLower)] 149 | [InlineData("T8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E891", MultibaseEncoding.Base32HexPaddedUpper)] 150 | [InlineData("het1sg3mqqt3gn5djxj11y3msci3817depfzgqejb", MultibaseEncoding.Base32Z)] 151 | [InlineData("Ztwe7gVTeK8wswS1gf8hrgAua9fcw9reboD", MultibaseEncoding.Base58Flickr)] 152 | [InlineData("zUXE7GvtEk8XTXs1GF8HSGbVA9FCX9SEBPe", MultibaseEncoding.Base58Btc)] 153 | [InlineData("mRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ", MultibaseEncoding.Base64)] 154 | [InlineData("MRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==", MultibaseEncoding.Base64Padded)] 155 | [InlineData("uRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ", MultibaseEncoding.Base64Url)] 156 | [InlineData("URGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==", MultibaseEncoding.Base64UrlPadded)] 157 | public void TestTryDecoding_GivenValidEncodedInput_Prefixed(string input, MultibaseEncoding encoding) 158 | { 159 | var expected = "Decentralize everything!!"; 160 | var result = Multibase.TryDecode(input, out var decodedEncoding, out var decodedBytes); 161 | 162 | Assert.True(result); 163 | Assert.Equal(encoding, decodedEncoding); 164 | Assert.Equal(expected, Encoding.UTF8.GetString(decodedBytes)); 165 | } 166 | 167 | [Theory] 168 | [InlineData("01000100011001010110001101100101011011100111010001110010011000010110110001101001011110100110010100100000011001010111011001100101011100100111100101110100011010000110100101101110011001110010000100100001", MultibaseEncoding.Base2)] 169 | [InlineData("1043126154533472162302661513646244031273145344745643206455631620441", MultibaseEncoding.Base8)] 170 | [InlineData("446563656e7472616c697a652065766572797468696e672121", MultibaseEncoding.Base16Lower)] 171 | [InlineData("446563656E7472616C697A652065766572797468696E672121", MultibaseEncoding.Base16Upper)] 172 | [InlineData("irswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb", MultibaseEncoding.Base32Lower)] 173 | [InlineData("IRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJB", MultibaseEncoding.Base32Upper)] 174 | [InlineData("8him6pbeehp62r39f9ii0pbmclp7it38d5n6e891", MultibaseEncoding.Base32HexLower)] 175 | [InlineData("8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E891", MultibaseEncoding.Base32HexUpper)] 176 | [InlineData("et1sg3mqqt3gn5djxj11y3msci3817depfzgqejb", MultibaseEncoding.Base32Z)] 177 | [InlineData("RGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==", MultibaseEncoding.Base64Padded)] 178 | public void TestTryDecoding_GivenValidEncodedInput_Unprefixed(string input, MultibaseEncoding encoding) 179 | { 180 | var expected = "Decentralize everything!!"; 181 | var result = Multibase.TryDecode(input, out var decodedEncoding, out var decodedBytes); 182 | 183 | Assert.True(result); 184 | Assert.Equal(encoding, decodedEncoding); 185 | Assert.Equal(expected, Encoding.UTF8.GetString(decodedBytes)); 186 | } 187 | 188 | // Official test vectors 189 | private static void TestVector(string encoding, string encoded, string expected) 190 | { 191 | var decoded = Multibase.Decode(encoded, out string mbEncoding); 192 | 193 | Assert.Equal(encoding, mbEncoding); 194 | Assert.Equal(expected, Encoding.UTF8.GetString(decoded)); 195 | 196 | var rencoded = Multibase.Encode(mbEncoding, decoded); 197 | 198 | Assert.Equal(encoded, rencoded); 199 | } 200 | 201 | [Theory] 202 | [CsvData("test1.csv")] 203 | public void TestVector_1(string encoding, string encoded) 204 | { 205 | var expected = "Decentralize everything!!"; 206 | 207 | TestVector(encoding, encoded, expected); 208 | } 209 | 210 | [Theory] 211 | [CsvData("test2.csv")] 212 | public void TestVector_2(string encoding, string encoded) 213 | { 214 | var expected = "yes mani !"; 215 | 216 | TestVector(encoding, encoded, expected); 217 | } 218 | 219 | [Theory] 220 | [CsvData("test3.csv")] 221 | public void TestVector_3(string encoding, string encoded) 222 | { 223 | var expected = "hello world"; 224 | 225 | TestVector(encoding, encoded, expected); 226 | } 227 | 228 | [Theory] 229 | [CsvData("test4.csv")] 230 | public void TestVector_4(string encoding, string encoded) 231 | { 232 | var expected = "\x00yes mani !"; 233 | 234 | TestVector(encoding, encoded, expected); 235 | } 236 | 237 | [Theory] 238 | [CsvData("test5.csv")] 239 | public void TestVector_5(string encoding, string encoded) 240 | { 241 | var expected = "\x00\x00yes mani !"; 242 | 243 | TestVector(encoding, encoded, expected); 244 | } 245 | 246 | [Theory] 247 | [CsvData("test6.csv")] 248 | public void TestVector_6(string encoding, string encoded) 249 | { 250 | var expected = "hello world"; 251 | 252 | var decoded = Multibase.Decode(encoded, out string mbEncoding, false); 253 | 254 | Assert.Equal(encoding, mbEncoding); 255 | Assert.Equal(expected, Encoding.UTF8.GetString(decoded)); 256 | } 257 | 258 | [Fact] 259 | public async Task TestBase58ConcurrentDecoding() 260 | { 261 | var tasks = Enumerable.Range(1, 10).Select(_ => Task.Run(() => 262 | { 263 | var success = Multibase.TryDecode("Z6BLZQNPgws5ahFtr8x", out var encoding, out var bytes); 264 | Assert.True(success); 265 | Assert.Equal(MultibaseEncoding.Base58Flickr, encoding); 266 | Assert.Equal("Concurrency !", Encoding.UTF8.GetString(bytes, 0, bytes.Length)); 267 | })); 268 | await Task.WhenAll(tasks); 269 | } 270 | } 271 | 272 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 273 | public class CsvDataAttribute : DataAttribute 274 | { 275 | private readonly string _fileName; 276 | public CsvDataAttribute(string fileName) 277 | { 278 | _fileName = fileName; 279 | } 280 | 281 | public override IEnumerable GetData(MethodInfo testMethod) 282 | { 283 | var pars = testMethod.GetParameters(); 284 | var parameterTypes = pars.Select(par => par.ParameterType).ToArray(); 285 | foreach (var line in File.ReadLines(_fileName).Skip(1)) 286 | { 287 | //csvFile.ReadLine();// Delimiter Row: "sep=,". Comment out if not used 288 | var row = line.Split(',').Select(c => c.Trim('"', ' ')).ToArray(); 289 | yield return ConvertParameters(row, parameterTypes); 290 | } 291 | } 292 | 293 | private static object[] ConvertParameters(IReadOnlyList values, IReadOnlyList parameterTypes) 294 | { 295 | var result = new object[parameterTypes.Count]; 296 | for (var idx = 0; idx < parameterTypes.Count; idx++) 297 | { 298 | result[idx] = ConvertParameter(values[idx], parameterTypes[idx]); 299 | } 300 | 301 | return result; 302 | } 303 | 304 | private static object ConvertParameter(object parameter, Type parameterType) 305 | { 306 | return parameterType == typeof(int) ? Convert.ToInt32(parameter) : parameter; 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/Multiformats.Base.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net461;netcoreapp2.2 5 | portable 6 | Multiformats.Base.Tests 7 | Multiformats.Base.Tests 8 | true 9 | 10 | 11 | 12 | 13 | 14 | false 15 | opencover 16 | [xunit.*]* 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | PreserveNewest 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/test1.csv: -------------------------------------------------------------------------------- 1 | encoding, "Decentralize everything!!" 2 | base2, "001000100011001010110001101100101011011100111010001110010011000010110110001101001011110100110010100100000011001010111011001100101011100100111100101110100011010000110100101101110011001110010000100100001" 3 | base8, "71043126154533472162302661513646244031273145344745643206455631620441" 4 | base16, "f446563656e7472616c697a652065766572797468696e672121" 5 | BASE16, "F446563656E7472616C697A652065766572797468696E672121" 6 | base32, "birswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb" 7 | BASE32, "BIRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJB" 8 | base32hex, "v8him6pbeehp62r39f9ii0pbmclp7it38d5n6e891" 9 | BASE32HEX, "V8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E891" 10 | base32pad, "cirswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb" 11 | BASE32PAD, "CIRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJB" 12 | base32hexpad, "t8him6pbeehp62r39f9ii0pbmclp7it38d5n6e891" 13 | BASE32HEXPAD, "T8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E891" 14 | base32z, "het1sg3mqqt3gn5djxj11y3msci3817depfzgqejb" 15 | base58flickr, "Ztwe7gVTeK8wswS1gf8hrgAua9fcw9reboD" 16 | base58btc, "zUXE7GvtEk8XTXs1GF8HSGbVA9FCX9SEBPe" 17 | base64, "mRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ" 18 | base64pad, "MRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==" 19 | base64url, "uRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ" 20 | base64urlpad, "URGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==" 21 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/test2.csv: -------------------------------------------------------------------------------- 1 | encoding, "yes mani !" 2 | base2, "001111001011001010111001100100000011011010110000101101110011010010010000000100001" 3 | base8, "7171312714403326055632220041" 4 | base16, "f796573206d616e692021" 5 | BASE16, "F796573206D616E692021" 6 | base32, "bpfsxgidnmfxgsibb" 7 | BASE32, "BPFSXGIDNMFXGSIBB" 8 | base32hex, "vf5in683dc5n6i811" 9 | BASE32HEX, "VF5IN683DC5N6I811" 10 | base32pad, "cpfsxgidnmfxgsibb" 11 | BASE32PAD, "CPFSXGIDNMFXGSIBB" 12 | base32hexpad, "tf5in683dc5n6i811" 13 | BASE32HEXPAD, "TF5IN683DC5N6I811" 14 | base32z, "hxf1zgedpcfzg1ebb" 15 | base58flickr, "Z7Pznk19XTTzBtx" 16 | base58btc, "z7paNL19xttacUY" 17 | base64, "meWVzIG1hbmkgIQ" 18 | base64pad, "MeWVzIG1hbmkgIQ==" 19 | base64url, "ueWVzIG1hbmkgIQ" 20 | base64urlpad, "UeWVzIG1hbmkgIQ==" 21 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/test3.csv: -------------------------------------------------------------------------------- 1 | encoding, "hello world" 2 | base2, "00110100001100101011011000110110001101111001000000111011101101111011100100110110001100100" 3 | base8, "7064145330661571007355734466144" 4 | base10, "9126207244316550804821666916" 5 | base16, "f68656c6c6f20776f726c64" 6 | BASE16, "F68656C6C6F20776F726C64" 7 | base32, "bnbswy3dpeb3w64tmmq" 8 | BASE32, "BNBSWY3DPEB3W64TMMQ" 9 | base32hex, "vd1imor3f41rmusjccg" 10 | BASE32HEX, "VD1IMOR3F41RMUSJCCG" 11 | base32pad, "cnbswy3dpeb3w64tmmq======" 12 | BASE32PAD, "CNBSWY3DPEB3W64TMMQ======" 13 | base32hexpad, "td1imor3f41rmusjccg======" 14 | BASE32HEXPAD, "TD1IMOR3F41RMUSJCCG======" 15 | base32z, "hpb1sa5dxrb5s6hucco" 16 | base58flickr, "ZrTu1dk6cWsRYjYu" 17 | base58btc, "zStV1DL6CwTryKyV" 18 | base64, "maGVsbG8gd29ybGQ" 19 | base64pad, "MaGVsbG8gd29ybGQ=" 20 | base64url, "uaGVsbG8gd29ybGQ" 21 | base64urlpad, "UaGVsbG8gd29ybGQ=" 22 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/test4.csv: -------------------------------------------------------------------------------- 1 | encoding, "\x00yes mani !" 2 | base2, "00000000001111001011001010111001100100000011011010110000101101110011010010010000000100001" 3 | base8, "7000171312714403326055632220041" 4 | base10, "90573277761329450583662625" 5 | base16, "f00796573206d616e692021" 6 | BASE16, "F00796573206D616E692021" 7 | base32, "bab4wk4zanvqw42jaee" 8 | BASE32, "BAB4WK4ZANVQW42JAEE" 9 | base32hex, "v01smasp0dlgmsq9044" 10 | BASE32HEX, "V01SMASP0DLGMSQ9044" 11 | base32pad, "cab4wk4zanvqw42jaee======" 12 | BASE32PAD, "CAB4WK4ZANVQW42JAEE======" 13 | base32hexpad, "t01smasp0dlgmsq9044======" 14 | BASE32HEXPAD, "T01SMASP0DLGMSQ9044======" 15 | base32z, "hybhskh3ypiosh4jyrr" 16 | base58flickr, "Z17Pznk19XTTzBtx" 17 | base58btc, "z17paNL19xttacUY" 18 | base64, "mAHllcyBtYW5pICE" 19 | base64pad, "MAHllcyBtYW5pICE=" 20 | base64url, "uAHllcyBtYW5pICE" 21 | base64urlpad, "UAHllcyBtYW5pICE=" 22 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/test5.csv: -------------------------------------------------------------------------------- 1 | encoding, "\x00\x00yes mani !" 2 | base2, "0000000000000000001111001011001010111001100100000011011010110000101101110011010010010000000100001" 3 | base8, "700000171312714403326055632220041" 4 | base16, "f0000796573206d616e692021" 5 | BASE16, "F0000796573206D616E692021" 6 | base32, "baaahszltebwwc3tjeaqq" 7 | BASE32, "BAAAHSZLTEBWWC3TJEAQQ" 8 | base32hex, "v0007ipbj41mm2rj940gg" 9 | BASE32HEX, "V0007IPBJ41MM2RJ940GG" 10 | base32pad, "caaahszltebwwc3tjeaqq====" 11 | BASE32PAD, "CAAAHSZLTEBWWC3TJEAQQ====" 12 | base32hexpad, "t0007ipbj41mm2rj940gg====" 13 | BASE32HEXPAD, "T0007IPBJ41MM2RJ940GG====" 14 | base32z, "hyyy813murbssn5ujryoo" 15 | base58flickr, "Z117Pznk19XTTzBtx" 16 | base58btc, "z117paNL19xttacUY" 17 | base64, "mAAB5ZXMgbWFuaSAh" 18 | base64pad, "MAAB5ZXMgbWFuaSAh" 19 | base64url, "uAAB5ZXMgbWFuaSAh" 20 | base64urlpad, "UAAB5ZXMgbWFuaSAh" 21 | -------------------------------------------------------------------------------- /test/Multiformats.Base.Tests/test6.csv: -------------------------------------------------------------------------------- 1 | non-canonical encoding, "hello world" 2 | base16, "f68656c6c6f20776F726C64" 3 | BASE16, "F68656c6c6f20776F726C64" 4 | base32, "bnbswy3dpeB3W64TMMQ" 5 | BASE32, "Bnbswy3dpeB3W64TMMQ" 6 | base32hex, "vd1imor3f41RMUSJCCG" 7 | BASE32HEX, "Vd1imor3f41RMUSJCCG" 8 | base32pad, "cnbswy3dpeB3W64TMMQ======" 9 | BASE32PAD, "Cnbswy3dpeB3W64TMMQ======" 10 | base32hexpad, "td1imor3f41RMUSJCCG======" 11 | BASE32HEXPAD, "Td1imor3f41RMUSJCCG======" 12 | --------------------------------------------------------------------------------