Code Monkey home page Code Monkey logo

swiftecc's People

Contributors

leif-ibsen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

swiftecc's Issues

ECIES standard

Hi,When I use bouncycastle to decrypt on the java side, iOS and java cannot decrypt each other.I want to know whether the ECIES standard in SwiftECC is ANSI X9.63 or IEEE 1363a?

Crypto Review Findings #4: Missing validations in reduction function

Vulnerability details

When using modular arithmetic, the application of a reduction function is necessary after each arithmetic operation, which ensures that the result is shifted into the expected value range.
There are many different methods for this task. The library under investigation uses the Barret reduction [1]. A clear presentation of the implemented method can be found in chapter 3.2 "General Barret Reduction" of [2].
The concrete implementation looks as follows [3]:

    func reduceModP(_ x: BInt) -> BInt {
        let x1 = x.isNegative ? -x : x
        var t = x1 - ((x1 * self.u) >> self.shifts) * self.p
        if t >= self.p {
            t -= self.p
        }
        return t.isZero ? BInt.ZERO : (x.isNegative ? self.p - t : t)
    }

From [3] also emerge the conditions that must be met for the algorithm to complete successfully. These checks are not fully implemented a priori.
For example, the procedure only works if
CodeCogsEqn (1)
but this is not checked. Additionally, in the above code line 3, a modulo operation provided in the actual algorithm is not performed.
In summary, the implemented procedure is equivalent to the one described in [2] if and only if

CodeCogsEqn

applies.

Countermeasures

A check of the allowed range of values for the input parameter x must be performed at the beginning of the function and an exception must be thrown in case of an error.

References

[1] P.Barret. Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor: https://link.springer.com/con- tent/pdf/10.1007%2F3-540-47721-7_24.pdf.
[2] C.Roma. Hardware Implementation of Barrett Reduction Exploiting Constant Multiplica- tion: https://uwspace.uwaterloo.ca/bitstream/handle/10012/15191/Roma_Crystal.pdf
[3] Source code of the reduceModP function: https://github.com/leif-ibsen/Swif- tECC/blob/621c70126966e5c289c4dc0ff801c6282b6baa05/Sources/SwiftECC/DomainP/Do mainP.swift#L218

Using AES256, how can I get iv in my code?

I'm using the next code:

func test() {
            let domain = Domain.instance(curve: .EC256k1)
            let (pubKey, privKey) = domain.makeKeyPair()
            let pubPEM = pubKey.pem
            let privPEM = privKey.pem

            print(pubPEM)
            print(privPEM)
 
            let object = MyObject()
            let jsonEncoder = JSONEncoder()
            let jsonData = try! jsonEncoder.encode(object)
            let json = String(data: jsonData, encoding: String.Encoding.utf8)

            let message = json!.data(using: .utf8)!

            let sig = privKey.sign(msg: message)
            let ok = pubKey.verify(signature: sig, msg: message)
            print(sig)

            let encrypted = pubKey.encrypt(msg: message, cipher: .AES256)
            print(encrypted)

            let decrypted = try! privKey.decrypt(msg: encrypted, cipher: .AES256)
            print(String(data: decrypted, encoding: .utf8))
}

How can I get iv here? It's required by the server

Crypto Review Findings #12: Scalar multiplication not in constant time

Vulnerability details

A relevant function in the arithmetic of a group spanned by an elliptic curve is the multiplication of a scalar by a curve point.
A traditional and very performant method for this is the Double-And-Add algorithm. However, this has the problem that the execution speed depends on the number and position of the 1-bits in the binary representation of the scalar value. If there is the possibility of a timing side channel, it may be possible to determine the value of the scalar. This is particularly critical, for example, in the generation of an ECDSA signature, where a secret scalar (the private key) is multiplied by a known point (the curve generator).

The library under study relies on an addition-subtraction ladder for this operation, which is described as Algorithm 7.2.4 in [1]. Also for this method the execution time depends on the binary representation of the scalar.

Countermeasures

To prevent the timing attacks described above, scalar multiplication should be performed in the form of a constant-time algorithm [2], where the execution time is independent of the concrete values of the input parameters.
The so-called Montgomery Ladder [3] has proven to be a very efficient and simple method for this purpose.

Severity: Info

⚠ The low rating of this vulnerability is based on the fact that only the verification of signatures is relevant in the context of this security review. For applications in which signatures are created or key pairs are generated, this is a more severe vulnerability.

References

[1] R.Crandall & C.Pomer. Prime Numbers. A computational perspective:
https://www.springer.com/gp/book/9780387252827
[2] D. Bernstein & T.Lange. SafeCurves: Ladders: https://safecurves.cr.yp.to/ladder.html
[3] D. Bernstein & T.Lange. Montgomery curves and the Montgomery ladder:
https://eprint.iacr.org/2017/293.pdf

Crypto Review Finding #2: Missing validations for ECDSA signature verification

Vulnerability details

The validation of an ECDSA signature is implemented in the PublicKey.swift file in the class ECPublicKey [1]:

The ECDSA procedure is well explained, for example, in Section 4.4.1 "ECDSA" of [2]. The algorithm for verifying such a signature is described in Algorithm 4.30 "ECDSA Signature Verification".

In this implementation, the following validation steps are not performed:

  1. it is not checked whether the two signature values r and s are between 1 and the group order order (step 1 in [2])
  2. it is not checked whether the calculated point R (X in [2]) is the far point of the curve (step 6 in [2])

This may lead to an incorrect result in the signature check [3].

Countermeasures

It is essential to complete the specified check steps in the specified function.

References

[1] Source code of the verify function: https://github.com/leif-ibsen/SwiftECC/blob/621c70126966e5c289c4dc0ff801c6282b6baa05/Sources/SwiftECC/PublicKey.sw
ift#L112
[2] D. Hankerson, A. Menezes, S. Vanstone. Guide to Elliptic Curve Cryptography:
https://www.springer.com/gp/book/9780387952734
[3] ECDSA Signature Verfication Checks: https://crypto.stackexchange.com/a/80252

Use of SymmetricKey for encryption/decryption

Hey @leif-ibsen

I guess there is no documentation in README for encryption/decryption with SymmetricKey.

I am struggling with encryption/decryption with use of SymmetricKey.
Could you please update the README ?
Also Could you please add example?

Thank you

Calculate ECDH shared secret the same way as in other frameworks

Can this library be used to calculate shared secret the same way as in Node or Java / Kotlin?

Here is the code that generates shared secret in Kotlin:

private fun computeSharedSecret(otherPublicKey: PublicKey, myPrivateKey: PrivateKey): ByteArray {
        val keyAgreement = KeyAgreement.getInstance("ECDH")
        keyAgreement.init(myPrivateKey)
        keyAgreement.doPhase(otherPublicKey, true)
        return keyAgreement.generateSecret()
    }

Here is the code in NodeJS

const myPrivateKey = Buffer.from("iUfaS6XxDCOS65sGqeunCQJR4045pTA3H4cCcYqfLpg", 'base64')
const otherSidePublicKey = Buffer.from("BJPPEL/HhVR4Yv8qyKT/1A8rcRhmP8aXBKCikXeShNhjWWWKjDuKt9zco7Flt9l14uJW1lt2kCIjb8e64wDW5Sg=", 'base64')

const ecdh = crypto.createECDH('secp256k1')
ecdh.setPrivateKey(myPrivateKey)
const sharedSecret = ecdh.computeSecret(otherSidePublicKey)

None of these example above use messageDigest or data parameter to calculate shared secret. Is it possible to calculate shared secret this way using SwiftECC?

Crypto Review Findings #16: Variable scope larger than necessary

Vulnerability details

In the decode function of the Base64 class, x is declared outside the for loop, but is not needed across loop calls.

public static func decode(_ input: String) throws -> Bytes { 
    var bytes: Bytes = []
    var eq = 0
    var i = 0
    var x = 0
    var bbbb = Bytes(repeating: 0, count: 4) for s in input {
        x = Int(s.unicodeScalars.first!.value)
    [...]
    }
    if i > 0 {
        throw ECException.base64
    }
    return bytes
}

Severity: Info

Countermeasures

We recommend declaring the variable x inside the for loop.

References

[1] Source code of the decode function in the Base64 class: https://github.com/leif-ibsen/SwiftECC/blob/621c70126966e5c289c4dc0ff801c6282b6baa05/Sources/SwiftECC/Base64.swift #L104

Decompression of EC key

Nice lib. Could you also implement decompression of EC key? Meaning computation of Y coordinate if there is given only X coordinate with prefix (= compressed key).

Crypto Review Finding #3 Faulty implementation of curve arithmetic

Vulnerability details

Any implementation of elliptic curves is based on the arithmetic operations, which are defined on the associated modular group. In particular, these include:

  • Addition of two points
  • Subtraction of two points
  • Doubling of a point
  • Multiplication of a point by a scalar
  • Modular arithmetic operations of scalars

Unfortunately, the examined library makes some mistakes in this implementation, which can subsequently lead to erroneous results in signature verification.

Incorrect reduction with modular addition and subtraction

After the addition or subtraction of two scalars, the result must be reduced modularly to fall back into the expected value range. This is done by the library in a very simple way [1]:

func addModP(_ x: BInt, _ y: BInt) -> BInt {
  let z = x + y
  return z >= self.p ? z - self.p : z
}

func subModP(_ x: BInt, _ y: BInt) -> BInt {
  let z = x - y
  return z.isNegative ? z + self.p : z
 }

However, this reduction is only correct if both input parameters x and y were already in the expected range of values, i.e. 0 ≤ 𝑥 < 𝑝 as well as 0 ≤ 𝑦 < 𝑝 holds. However, this fact is not verified in the code.

Missing point verification

In the methods the following methods of the Domain or DomainP classes, no point verification is performed at the beginning:

  • double() (doubling of one point)
  • add() (Addition of 2 points)
  • subtract() (Subtraction of 2 points)
  • negate() (Calculation of the inverse element)
  • multiply() (multiplication of a point by a scalar)

This means that points can be passed as input parameters that are not on the curve at all. This can, especially in the context of the Elliptic Curve Diffie-Hellman (ECDHI) method, lead to a so-called Invalid Curve Attack [2].
The faulty methods look like the following [3]:

public func double(_ p: Point) -> Point {
 return self.characteristic2 ? self.domain2!.double(Point2.fromPoint(domain2!.rp, p)).toPoint() : self.domainP!.double(p)
}

public func add(_ p1: Point, _ p2: Point) -> Point {
 return self.characteristic2 ? self.domain2!.add(Point2.fromPoint(domain2!.rp, p1), Point2.fromPoint(domain2!.rp, p2)).toPoint() : self.domainP!.add(p1, p2)
}

public func subtract(_ p1: Point, _ p2: Point) -> Point { 
    return self.characteristic2 ? self.domain2!.subtract(Point2.fromPoint(domain2!.rp, p1), Point2.fromPoint(domain2!.rp, p2)).toPoint() : self.domainP!.subtract(p1, p2)
}

public func negate(_ p: Point) -> Point { 
    return self.characteristic2 ? self.domain2!.negate(Point2.fromPoint(domain2!.rp, p)).toPoint() : self.domainP!.negate(p) 
}

public func multiply(_ p: Point, _ n: BInt) -> Point { 
    return self.characteristic2 ? self.domain2!.multiply(Point2.fromPoint(domain2!.rp, p), n).toPoint() : self.domainP!.multiply(p, n)
}

Currently, such a check of the points (using the contains() method of the Domain class is only performed when decoding ASN.1 encoded points, but not when using manually instantiated points.

Countermeasures

Incorrect reduction for modular addition and subtraction.

As a minimal solution, it should be checked at the beginning whether the input parameters fall within the expected range of values. It would be better to rely on the reduceModP reduction function already available in the same class here instead of a manual implementation, but this may be associated with speed losses.

Missing point verification

Before any arithmetic operation it must be ensured that the points passed as input parameter actually lie on the underlying elliptic curve.

Error in MessageDigest using sha1 algorithm

Hi, when I tried to modify the source code, I found a problem. I need to use the sha1 algorithm to decrypt the data. The current MessageDigest uses the sha256 algorithm. When I modify it to sha1, the encryption and decryption will report an error, "Fatal error: Array index is out of range "
1673942164467

Generating key agreement takes over 500ms

How to reproduce:

let domain256k1 = Domain.instance(curve: .EC256r1)

let k1 = domain256k1.makeKeyPair()
let k2 = domain256k1.makeKeyPair()

let from = DispatchTime.now().uptimeNanoseconds

try k1.1.keyAgreement(pubKey: k2.0, length: 32, md: .SHA1, sharedInfo: []) // 👈 here

let now = DispatchTime.now().uptimeNanoseconds
let fromNow = String(Double(now - from) / 1_000_000_000)
print("took: " + fromNow + " sec") // Running this on my M1 Max MacBook Pro prints `took: 0.534008709 sec`

The current implementation exhibits slower performance even compared to Javascript implementations such as crypto-browserify or the node:crypto package, which finish the task within a few milliseconds. Even Java implementation with BouncyCastle is faster

Upon exploring the code, it appears that this line. could be contributing to the slower performance.

Invalid x, y components from generated BP256r1 keypair

  1. We generate a keypair
    let (asymPublicKey, _) = Domain.instance(curve: .BP256r1).makeKeyPair()

  2. Get x and y components from the public key
    asymPublicKey.w.x.asMagnitudeBytes()
    asymPublicKey.w.y.asMagnitudeBytes()

  3. Then we use this information to send a rather complicated backend request and receive the following error
    could not create public key from x,y components - elliptic curve point is not on curve

We only get this error about once per 30 requests.

For example, with the following keypair the error is reproducible:
PublicKey:

-----BEGIN PUBLIC KEY-----
MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABIUCEqHiyt6ENtryBdxEk9Wrwy/W
XXSv4Lefh2nBR7XWAPZVcbKUAhr2s0oRS+ceE6tEl+HM157wr8tguXQ4Xbo=
-----END PUBLIC KEY-----

PrivateKey:

-----BEGIN EC PRIVATE KEY-----
MHgCAQEEIHctkCXo/LMh1qxqt7uL/wjTKU/RBpGEMngiCsvlmOevoAsGCSskAwMC
CAEBB6FEA0IABIUCEqHiyt6ENtryBdxEk9Wrwy/WXXSv4Lefh2nBR7XWAPZVcbKU
Ahr2s0oRS+ceE6tEl+HM157wr8tguXQ4Xbo=
-----END EC PRIVATE KEY-----

This error is related to V4 and V5.

Load existing Key by Hex-string or Bytes

I'm currently having a issue of loading my existing eth keys into ECPrivateKey, but i'm not able to come up with the pem or der format it needs, so i am wondering if there is a way to get pem/der format or just having a another alternative way to load my existing keys?

Arithmetic operation '-1060120681 * 31' (on type 'Int') results in an overflow

Greetings,

Steps to reproduce

  1. Create a new project with the package.
  2. Choose "Any iOS Device" to build.
  3. Start building.

Error

Arithmetic operation '-1060120681 * 31' (on type 'Int') results in an overflow.

    // Small prime product
    static let SPP = BInt(3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 * 31 * 37 * 41)

Possible solution

Replace multiplication with initialization from String:

static let SPP = BInt("152125131763605")!

Crypto Review Finding #14: Curve verification for signature verification could be improved

Vulnerability details

Among other things, the constructor of the ECSignature class can be passed an object of type Domain, which is subsequently used for padding the two signature values [1]:

public convenience init(asn1: ASN1, domain: Domain) throws { 
    guard let seq = asn1 as? ASN1Sequence else {
        throw ECException.asn1Structure
    }

    if seq.getValue().count < 2 {
        throw ECException.asn1Structure 
    }
    
    guard let r0 = seq.get(0) as? ASN1Integer else {
        throw ECException.asn1Structure
    }
 
    guard let s1 = seq.get(1) as? ASN1Integer else {
        throw ECException.asn1Structure
    }    
    self.init(r: domain.align(r0.value.asMagnitudeBytes()), s:domain.align(s1.value.asMagnitudeBytes()))
}

However, the curve type obtained here is not stored in the class, but discarded after the constructor terminates. This leads to the fact that the signature can be checked unnoticed with an ECPublicKey object, which was created for another curve.
As long as the signature values in the constructor are not changed in content, this should not affect the result of the verification, but it leads to less efficient error detection.

Countermeasures

If the curve specified in the constructor is stored within the class, then this value can be matched against the curve used for the key right at the start of the ECPublikKey.verify() method, and immediately terminated with a matching error if necessary.

Severity: Info

References
[1] Source code of the constructor of the ECSignature class: https://github.com/leif-ibsen/SwiftECC/blob/621c70126966e5c289c4dc0ff801c6282b6baa05/Sources/SwiftECC/Signature.sw ift#L34

Crypto Review Findings #11 - Use of non-standard curves is possible

Vulnerability details

Theoretically, it is possible to define an infinite number of different elliptic curves. However, it has been found that only a small number of these curves are actually usable for cryptographically secure deployment. The definition of the individual curve parameters is an extremely difficult matter, and even small errors can substantially impair the security or speed of the procedures based on them. [1]
It is therefore strongly recommended to use only standardized curves published by well-known organizations such as the IETF, NIST, or BSI for the cryptographic use of elliptic curves.

Furthermore, in recent years it has been recognized that a free definability of parameters in a cryptographic protocol, a cryptographic agility or cipher agility can severely limit security [2].
The studied library provides the possibility to use arbitrary elliptic curves. The is evident in the domainFromASN1 method of the Domain class, which is called when parsing a public key, among other things [3]:

static func domainFromASN1(_ asn1: ASN1) throws -> Domain { 
    if let oid = asn1 as? ASN1ObjectIdentifier {
        return try Domain.instance(oid: oid)
    }

    [...]

    guard let aa = seq2.get(0) as? ASN1OctetString else {
        throw ECException.asn1Structure
    }

    guard let bb = seq2.get(1) as? ASN1OctetString else {
        throw ECException.asn1Structure
    }

    let a = BInt(magnitude: aa.value)
    let b = BInt(magnitude: bb.value)
    guard let g = seq.get(3) as? ASN1OctetString else {
        throw ECException.asn1Structure 
    }

    if g.value.count & 0x1 == 0 || g.value[0] != 4 { 
        throw ECException.asn1Structure
    }

    let l = (g.value.count - 1) / 2
    let gx = BInt(magnitude: Bytes(g.value[1 ..< l + 1]))
    let gy = BInt(magnitude: Bytes(g.value[l + 1 ..< g.value.count]))
    
    guard let ord = seq.get(4) as? ASN1Integer else {
        throw ECException.asn1Structure
    }

    let order = ord.value
    guard let co = seq.get(5) as? ASN1Integer else {
        throw ECException.asn1Structure
    }

    if !co.value.isPositive {
        throw ECException.asn1Structure
    }

    let cofactor = co.value.asInt()! 34 [...]
 }

In this function, not only is the specification of a standard curve by OID (lines 2-4) allowed, but also the direct specification of freely chosen curve parameters.
Since this information often comes from untrusted sources (e.g., if the public key is included in a signature), this can be used for an attack where the calculation is forced on a deliberately insecure curve.

Countermeasures

The use of non-standard curves is generally to be classified as insecure. We therefore recommend to generally remove their usability in the library, or at least only allow them if a special unsafe mode has been manually activated (e.g. via compiler flag).

References

[1] D. Bernstein & T.Lange. SafeCurves: choosing safe curves for elliptic-curve cryptography:
https://safecurves.cr.yp.to/index.html
[2] Scott Arciszewski. Against Cipher Agility in Cryptography Protocols: https://paragonie.com/blog/2019/10/against-cipher-agility-in-cryptography-protocols
[3] Source code of the domainFromASN1 function: https://github.com/leif-ibsen/SwiftECC/blob/621c70126966e5c289c4dc0ff801c6282b6baa05/Sources/SwiftECC/Domain.swift #L517

Xcode 13.0 support

What happened?

Currently when you want to upgrade from Xcode 12.* to Xcode 13.0 the SwiftECC library is not going to build due to the following message:

SwiftECC/Sources/SwiftECC/PrivateKey.swift:180:41:  integer literal '4294967295' overflows when stored into 'Int'
        if length >= mda.digestLength * 0xffffffff || length < 0 {

Versions

  • Xcode: 13.0
  • SwiftECC: 2.2.0

Dependency naming collision with other crypto lib

Hi Leif,

We are trying to use SwiftECC in the same project as Shield.

Both have a sub-dependency to a package called BigInt.

Unfortunately, Swift Package Manager does not provide any ways to resolve this kind of ambiguity. See here fore a similar issue.

Therefore, I wanted to ask if there is an option for you to refactor your BigInt dependency to a different name.

All the best,
Lorenz

Licensing

Hi,

Currently this project doesn't have a License. This makes it impossible to use in another app legally.
Could we add an License?

Proposal
I think the MIT License would be good for this project, as it allows a bigger community to use this library.

We'd just have to add a LICENSE document in the root with the MIT License.

How to export the base64 string after ECDSA signature?

func ecdsaSignature(_ params: String) {
        guard let privateKey = try? ECPrivateKey(pem: pkey) else {
            return
        }
        let message = params.data(using: .utf8)!
        let sig = privateKey.sign(msg: message)
        
        print(sig.description)
          
        let publicKey = ECPublicKey(privateKey: privateKey)
        let ok = publicKey.verify(signature: sig, msg: message)
        
        print(ok)
    }

'SymmetricKey' is only available in iOS 13.0 or newer

Version of lib: 3.5.0
Project with included library not compilling with this errors
IMG

System and project settings
Xcode 14.1
Swift 5 (latests which is used in 14.1 xcode)
Base SDK in project 14.0 (CryptoKit is available)

Version 3.4.0 compiled fine!

objc

can this library be used in an objc application?

Crypto Review Finding #1: Missing unit tests

Vulnerability details

There are currently no or only incomplete unit tests for the following classes, which means that a faulty implementation would remain undetected currently or in the future.

SHA-2

The library uses its own implementation of the hash procedure SHA-2[1]. This is used, among other things, in the creation and validation of ECDSA signatures.

Arithmetic and signatures with Brainpool curves

For ECDSA signatures using Brainpool curves, there are no known-answer tests that can ensure the correctness of the procedure compared to other implementations. There is only an attempt to re-verify data signed by the library itself. Unfortunately, a verification of an externally created signature or a validation of the arithmetic does not take place.

Countermeasures

SHA-2

All variants of the SHA-2 family should be subjected to rigorous unit testing within the library.

Arithmetic and signatures with brainpool curves

Both for the arithmetic of the curves (addition, scalar multiplication, ...) and for ECDSA signatures, unit tests should be created with externally validated test data.

In all cases, standardized test vectors should be used whenever possible [2] [3]. If no such vectors are available, test data should be created using established software from another vendor (e.g. OpenSSL).

[1] https://github.com/leif-ibsen/SwiftECC/blob/1.0.2/Sources/SwiftECC/Cipher/SHA2.swift

[2]NIST. The Secure Hash AlgorithmValidation System (SHAVS): https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Pro-gram/documents/shs/SHAVS.pdf

[3]L.Bruckert et.al. RFC 8734: ECC Brainpool Curves Test vectors: https://www.rfc-edi-tor.org/rfc/rfc8734#name-test-vectors

Can I use it with Cocoapods?

I would like to use this library through Cocoapods, why don't you want to add support for this? Cocoapods is the most popular dependency manager

Support for curve25519

Hi,

is it possible to add curve25519 domain for creating the EC keys?

I'm relatively new but this library has helped me so far. But our requirement is to implement Curve25519 encryption.. so please let me know how I can create a curve25519 domain public key.

We are interested in using your Library in one of our Applications

Hi Leif,

Thank you for your great work on this library.

We are considering using it in one of our applications. As security is extremely relevant for our purpose, we would like to have this library reviewed by a company specialised in the field.

If anything comes up during the review, we would like to create pull requests so that the findings flow back into the library.

Are you open for this kind of cooperation? Please contact me via [email protected] if you want to discuss this issue directly.

Best,
Lorenz

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.