Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mdehoog committed Nov 29, 2024
0 parents commit 3e1b3fc
Show file tree
Hide file tree
Showing 15 changed files with 2,045 additions and 0 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Show Forge version
run: |
forge --version
- name: Run Forge fmt
run: |
forge fmt --check
id: fmt

- name: Run Forge build
run: |
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test -vvv
id: test
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env
/.idea/
/.DS_Store
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
22 changes: 22 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
(The MIT License)

Copyright 2020-2024

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6 changes: 6 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions lib/forge-std
Submodule forge-std added at 1eea5b
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
forge-std/=lib/forge-std/src/
192 changes: 192 additions & 0 deletions src/Asn1Decode.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// SPDX-License-Identifier: MIT

// Copyright (c) 2019 Jonah Groendal

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

pragma solidity ^0.8.15;

// adapted from https://github.com/JonahGroendal/asn1-decode/tree/master

import {NodePtr, LibNodePtr} from "./NodePtr.sol";
import {LibBytes} from "./LibBytes.sol";

library Asn1Decode {
using LibNodePtr for NodePtr;
using LibBytes for bytes;

/*
* @dev Get the root node. First step in traversing an ASN1 structure
* @param der The DER-encoded ASN1 structure
* @return A pointer to the outermost node
*/
function root(bytes memory der) internal pure returns (NodePtr) {
return readNodeLength(der, 0);
}

/*
* @dev Get a child root of the current node
* @param der The DER-encoded ASN1 structure
* @param ptr Pointer to the current node
* @return A pointer to the child root node
*/
function rootOf(bytes memory der, NodePtr ptr) internal pure returns (NodePtr) {
return readNodeLength(der, ptr.content());
}

/*
* @dev Get the next sibling node
* @param der The DER-encoded ASN1 structure
* @param ptr Points to the indices of the current node
* @return A pointer to the next sibling node
*/
function nextSiblingOf(bytes memory der, NodePtr ptr) internal pure returns (NodePtr) {
return readNodeLength(der, ptr.content() + ptr.length());
}

/*
* @dev Get the first child node of the current node
* @param der The DER-encoded ASN1 structure
* @param ptr Points to the indices of the current node
* @return A pointer to the first child node
*/
function firstChildOf(bytes memory der, NodePtr ptr) internal pure returns (NodePtr) {
require(der[ptr.header()] & 0x20 == 0x20, "Not a constructed type");
return readNodeLength(der, ptr.content());
}

/*
* @dev Extract value of bitstring node from DER-encoded structure
* @param der The DER-encoded ASN1 structure
* @param ptr Points to the indices of the current node
* @return Value of bitstring converted to bytes
*/
function bitstringAt(bytes memory der, NodePtr ptr) internal pure returns (NodePtr) {
require(der[ptr.header()] == 0x03, "Not type BIT STRING");
// Only 00 padded bitstr can be converted to bytestr!
require(der[ptr.content()] == 0x00);
return LibNodePtr.toNodePtr(ptr.header(), ptr.content() + 1, ptr.length() - 1);
}

/*
* @dev Extract value of node from DER-encoded structure
* @param der The der-encoded ASN1 structure
* @param ptr Points to the indices of the current node
* @return Uint value of node
*/
function uintAt(bytes memory der, NodePtr ptr) internal pure returns (uint256) {
require(der[ptr.header()] == 0x02, "Not type INTEGER");
require(der[ptr.content()] & 0x80 == 0, "Not positive");
uint256 len = ptr.length();
return uint256(readBytesN(der, ptr.content(), len) >> (32 - len) * 8);
}

function uint384At(bytes memory der, NodePtr ptr) internal pure returns (uint128, uint256) {
require(der[ptr.header()] == 0x02, "Not type INTEGER");
require(der[ptr.content()] & 0x80 == 0, "Not positive");
uint256 valueLength = ptr.length();
uint256 start = ptr.content();
if (der[start] == 0) {
start++;
valueLength--;
}
return (
uint128(uint256(readBytesN(der, start, 16) >> 128)),
uint256(readBytesN(der, start + 16, valueLength - 16) >> (48 - valueLength) * 8)
);
}

function timestampAt(bytes memory der, NodePtr ptr) internal pure returns (uint256) {
uint16 _years;
uint256 offset = ptr.content();
uint256 length = ptr.length();

if (length == 13) {
_years = (uint8(der[offset]) - 48 < 5) ? 2000 : 1900;
} else {
_years = (uint8(der[offset]) - 48) * 1000 + (uint8(der[offset + 1]) - 48) * 100;
offset += 2;
}
_years += (uint8(der[offset]) - 48) * 10 + uint8(der[offset + 1]) - 48;
uint8 _months = (uint8(der[offset + 2]) - 48) * 10 + uint8(der[offset + 3]) - 48;
uint8 _days = (uint8(der[offset + 4]) - 48) * 10 + uint8(der[offset + 5]) - 48;
uint8 _hours = (uint8(der[offset + 6]) - 48) * 10 + uint8(der[offset + 7]) - 48;
uint8 _mins = (uint8(der[offset + 8]) - 48) * 10 + uint8(der[offset + 9]) - 48;
uint8 _secs = (uint8(der[offset + 10]) - 48) * 10 + uint8(der[offset + 11]) - 48;

return timestampFromDateTime(_years, _months, _days, _hours, _mins, _secs);
}

function byteAtOffset(bytes memory der, NodePtr ptr, uint256 offset) internal pure returns (bytes1) {
return der[ptr.content() + offset];
}

function readNodeLength(bytes memory der, uint256 ix) private pure returns (NodePtr) {
uint256 length;
uint80 ixFirstContentByte;
if ((der[ix + 1] & 0x80) == 0) {
length = uint8(der[ix + 1]);
ixFirstContentByte = uint80(ix + 2);
} else {
uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F);
if (lengthbytesLength == 1) {
length = uint8(der[ix + 2]);
} else if (lengthbytesLength == 2) {
length = der.readUint16(ix + 2);
} else {
length = uint256(readBytesN(der, ix + 2, lengthbytesLength) >> (32 - lengthbytesLength) * 8);
}
ixFirstContentByte = uint80(ix + 2 + lengthbytesLength);
}
return LibNodePtr.toNodePtr(ix, ixFirstContentByte, uint80(length));
}

function readBytesN(bytes memory self, uint256 idx, uint256 len) private pure returns (bytes32 ret) {
require(len <= 32);
require(idx + len <= self.length);
assembly {
let mask := not(sub(exp(256, sub(32, len)), 1))
ret := and(mload(add(add(self, 32), idx)), mask)
}
}

// Calculate the number of seconds from 1970/01/01 to
// year/month/day/hour/minute/second using the date conversion
// algorithm from https://aa.usno.navy.mil/faq/JD_formula.html
// and subtracting the offset 2440588 so that 1970/01/01 is day 0
function timestampFromDateTime(
uint256 year,
uint256 month,
uint256 day,
uint256 hour,
uint256 minute,
uint256 second
) private pure returns (uint256) {
require(year >= 1970);
int256 _year = int256(year);
int256 _month = int256(month);
int256 _day = int256(day);

int256 _days = _day - 32075 + 1461 * (_year + 4800 + (_month - 14) / 12) / 4
+ 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12 - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4
- 2440588;

return ((uint256(_days) * 24 + hour) * 60 + minute) * 60 + second;
}
}
Loading

0 comments on commit 3e1b3fc

Please sign in to comment.