Path Parameters
You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
The value of the path parameter item_id
will be passed to your function as the argument item_id
.
So, if you run this example and go to http://<IP_ADDRESS>:8000/items/foo, you will see a response of:
{"item_id":"foo"}
Path parameters with types¶
You can declare the type of a path parameter in the function, using standard Python type annotations:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
In this case, item_id
is declared to be an int
.
Check
This will give you editor support inside of your function, with error checks, completion, etc.
Data conversion¶
If you run this example and open your browser at http://<IP_ADDRESS>:8000/items/3, you will see a response of:
{"item_id":3}
Check
Notice that the value your function received (and returned) is 3
, as a Python int
, not a string "3"
.
So, with that type declaration, FastAPI gives you automatic request "parsing".
Data validation¶
But if you go to the browser at http://<IP_ADDRESS>:8000/items/foo, you will see a nice HTTP error of:
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
because the path parameter item_id
had a value of "foo"
, which is not an int
.
The same error would appear if you provided a float
instead of an int, as in: http://<IP_ADDRESS>:8000/items/4.2
Check
So, with the same Python type declaration, FastAPI gives you data validation.
Notice that the error also clearly states exactly the point where the validation didn't pass.
This is incredibly helpful while developing and debugging code that interacts with your API.
Documentation¶
And when you open your browser at http://<IP_ADDRESS>:8000/docs, you will see an automatic, interactive, API documentation like:
Check
Again, just with that same Python type declaration, FastAPI gives you automatic, interactive documentation (integrating Swagger UI).
Notice that the path parameter is declared to be an integer.
Standards-based benefits, alternative documentation¶
And because the generated schema is from the OpenAPI standard, there are many compatible tools.
Because of this, FastAPI itself provides an alternative API documentation (using ReDoc):
The same way, there are many compatible tools. Including code generation tools for many languages.
Pydantic¶
All the data validation is performed under the hood by Pydantic, so you get all the benefits from it. And you know you are in good hands.
You can use the same type declarations with str
, float
, bool
and many other complex data types.
Several of these are explored in the next chapters of the tutorial.
Order matters¶
When creating path operations, you can find situations where you have a fixed path.
Like /users/me
, let's say that it's to get data about the current user.
And then you can also have a path /users/{user_id}
to get data about a specific user by some user ID.
Because path operations are evaluated in order, you need to make sure that the path for /users/me
is declared before the one for /users/{user_id}
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
Otherwise, the path for /users/{user_id}
would match also for /users/me
, "thinking" that it's receiving a parameter user_id
with a value of "me"
.
Predefined values¶
If you have a path operation that receives a path parameter, but you want the possible valid path parameter values to be predefined, you can use a standard Python Enum
.
Create an Enum
class¶
Import Enum
and create a sub-class that inherits from str
and from Enum
.
By inheriting from str
the API docs will be able to know that the values must be of type string
and will be able to render correctly.
And create class attributes with fixed values, those fixed values will be the available valid values:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Info
Enumerations (or enums) are available in Python since version 3.4.
Tip
If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning models.
Declare a path parameter¶
Then create a path parameter with a type annotation using the enum class you created (ModelName
):
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Check the docs¶
Because the available values for the path parameter are specified, the interactive docs can show them nicely:
Working with Python enumerations¶
The value of the path parameter will be an enumeration member.
Compare enumeration members¶
You can compare it with the enumeration member in your created enum ModelName
:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Get the enumeration value¶
You can get the actual value (a str
in this case) using model_name.value
, or in general, your_enum_member.value
:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Tip
You could also access the value "lenet"
with ModelName.lenet.value
.
Return enumeration members¶
You can return enum members from your path operation, even nested in a JSON body (e.g. a dict
).
They will be converted to their corresponding values before returning them to the client:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Path parameters containing paths¶
Let's say you have a path operation with a path /files/{file_path}
.
But you need file_path
itself to contain a path, like home/johndoe/myfile.txt
.
So, the URL for that file would be something like: /files/home/johndoe/myfile.txt
.
OpenAPI support¶
OpenAPI doesn't support a way to declare a path parameter to contain a path inside, as that could lead to scenarios that are difficult to test and define.
Nevertheless, you can still do it in FastAPI, using one of the internal tools from Starlette.
And the docs would still work, although not adding any documentation telling that the parameter should contain a path.
Path convertor¶
Using an option directly from Starlette you can declare a path parameter containing a path using a URL like:
/files/{file_path:path}
In this case, the name of the parameter is file_path
, and the last part, :path
, tells it that the parameter should match any path.
So, you can use it with:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_user_me(file_path: str):
return {"file_path": file_path}
Tip
You could need the parameter to contain /home/johndoe/myfile.txt
, with a leading slash (/
).
In that case, the URL would be: /files//home/johndoe/myfile.txt
, with a double slash (//
) between files
and home
.
Recap¶
With FastAPI, by using short, intuitive and standard Python type declarations, you get:
- Editor support: error checks, autocompletion, etc.
- Data "parsing"
- Data validation
- API annotation and automatic documentation
And you only have to declare them once.
That's probably the main visible advantage of FastAPI compared to alternative frameworks (apart from the raw performance).


show for in
The following table was created manually by screenshotting and slicing test.html. The Panel above allows filtering the table and switching normal/focus styles (toggled by space).
| What | Firefox | Chrome | Safari | IE11 | ||
|---|---|---|---|---|---|---|
| Mac | Win | Mac | Win | Mac | Win | |
| text input with native appearance and native focus style | ||||||
| text input with native appearance and custom focus style | ||||||
| text input with appearance:none and native focus style | ||||||
| text input with appearance:none and custom focus style | ||||||
| checkbox input with native appearance and native focus style | ||||||
| checkbox input with native appearance and custom focus style | ||||||
| checkbox input with custom appearance and native focus style | ||||||
| checkbox input with custom appearance and custom focus style | ||||||
| radio input with native appearance and native focus style | ||||||
| radio input with native appearance and custom focus style | ||||||
| radio input with custom appearance and native focus style | ||||||
| radio input with custom appearance and custom focus style | ||||||
| button with native appearance and native focus style | ||||||
| button with native appearance and custom focus style | ||||||
| button with appearance:none and native focus style | ||||||
| button with appearance:none and native custom style | ||||||
| button with custom appearance and native focus style | ||||||
| button with custom appearance and native custom style | ||||||
| textarea with native appearance and native focus style | ||||||
| textarea with native appearance and custom focus style | ||||||
| textarea with appearance:none and native focus style | ||||||
| textarea with appearance:none and custom focus style | ||||||
| textarea with custom appearance and native focus style | ||||||
| textarea with custom appearance and custom focus style | ||||||
| link with native focus style | ||||||
| link with custom focus style | ||||||
| div with native focus style | ||||||
| div with custom focus style |


The raw track object
The paused duration of the track (if playing and paused atleast once)
The playback duration of the track (if playing)
The track source type
The track url or location
Add a pause timestamp when track is paused
The timestamp when the track is paused
Add a unpause timestamp when track is unpaused
The timestamp when the track is unpaused
Cleanup timestamps after track is stopped playing
Get value of a track metadata property
The metadata property key
The metadata property value
Set a value to a track metadata property
The metadata property key
The metadata property value to set
Set the audio player which play the track
The audio player
Generated using TypeDoc
Track instance of the raw track


Judges 11:32
So Jephthah passed over unto the children of Ammon to fight against them; and the LORD delivered them into his hands.


Simple Selection of Country and State
Select Country
Select Country
India
Spain
Qatar
Egypt
Australia
Select State
Select State
Author:
Mahesh Muttinti


While I was born in Portland, I moved around the Pacific Northewst frequently while growing up. This has now transitioned into a love of travel and new environments. I used to consider myself another Portlander who needs our generally-overcast skies and bouts of rain, but I've found that I might prefer to move somewhere much sunnier. I'm confident that the skills I'll be learning over the next few months will prove to be useful tools in my future endeavors. I live in Portland's CEID neighborhod with my partner and two animals: A dog and a cat. My cat very much prefers his privacy, but I'm happy to show off my other furry friend:
My favorite parts about living in my neighborhod, in order:
Have a question or some feedback for me? Feel free to email me!


Flyweight works by splitting up an object into an intrinsic part that can be shared with
other objects and an extrinsic part that is unique to that specific object. Flyweight
uses another software design pattern,
Fig. 01: Flyweight Design Explained through Factory Methodology.
In video games there are many examples of objects which may share some things in common but also have unique features. An example of this could be textured squares on a game screen. Whilst they may all share the same texture they all have a unique position in the game world. The flyweight object holds the repeated texture intrinsically, whilst the subclasses hold their unique co-ordinates in the game world extrinsically. This helps reduce memory usage as the texture is not repeated in all the objects. Memory usage is often very critical in game performance and a sizable reduction in memory usage can be achieved through the flyweight method.
1. Why would you want to use a flyweight design pattern?
2. Which of the following does NOT happen in flyweight?
3. What is the class relationship in flyweight?
4. TRUE/FALSE: You would use flyweight pattern when the objects created may include info that is duplicated .
5. TRUE/FALSE: Flyweight composes objects in a hierarchy using a tree structure.
6. TRUE/FALSE: Flyweight is a structural pattern.
Incorrect! The correct answer to Question 1 is Answer B.
Incorrect! The correct answer to Question 2 is Answer C.
Incorrect! The correct answer to Question 3 is Answer A.
Incorrect! The correct answer to Question 4 is Answer A.
Incorrect! The correct answer to Question 5 is Answer B.
Incorrect! The correct answer to Question 6 is Answer A.
You answered them all right!


Currently I am working on my capstone project at SendGrid. SendGrid helps companies send their emails to customers. I am working with Go language, MySQL, and Grafana. My team and I are attempting to maximize the way an emails are searched in the database. We are using the bloom filter data structures to create a client/server simulation. This project is still under way and I expect to post more on it soon.
This project involved conducting research in the form of user interviews, competitive analysis, use cases, scenarios etc. to improve the user experience for the Yummi application. Yummi is a food journaling application. My team and I enhanced the user’s posting and filtering experience. The filter feature will allow users to browse through their and friends’ photos in an easier and more efficient manner just as the posting feature will also be efficient.


-
Jo Littlefair
Winner, Interior Designer of the Year
The Brit List Awards 2019
-
David Hood
Shortlisted, Architect of the Year
The Brit List Awards 2019
-
Hilton Imperial Dubrovnik
Shortlisted, Hotel Bedroom & Suites Design
Client:
HiltonWIN AWARDS 2019
-
Hilton Imperial Dubrovnik
Shortlisted, Hotel Bedroom & Suites Design
Client:
Hilton[d]arc awards, 2019
-
Juliet Rose Bar
Shortlisted, Bar, Club or Lounge
Client:
HiltonAHEAD Europe Awards, 2019
view project
-
The Lowry Hotel
Shortlisted, Hotel Bedroom & Suites Design
Client:
The Lowry HotelSBID International Design Awards, 2019
view project
-
Hilton Imperial Dubrovnik
Shortlisted, Hotel Bedroom & Suites Design
Client:
HiltonSBID International Design Awards, 2019
view project
-
Hilton Imperial Dubrovnik
Shortlisted, Hotel Public Space Design
Client:
HiltonSBID International Design Awards, 2019
view project
-
Goddard Littlefair
Winner, Top Interior Designer (UK)
NEWH Top ID Awards, 2019
-
The Hilton Imperial Dubrovnik
Winner, Hotel Interiors Project of the Year
Client:
HiltonMixology Awards, 2019
view project
-
Imperial Bar & Lounge
Shortlisted, Lighting Design
Client:
HiltonRestaurant & Bar Design Awards, 2019
view project
-
Imperial Bar & Lounge
Shortlisted, Hotel Bar Design
Client:
HiltonRestaurant & Bar Design Awards, 2019
view project
-
The Lowry Presidential Suite
Shortlisted, Project of the Year
Client:
CDL HospitalityNorth West Regional Construction Awards, 2019
view project
-
Goddard Littlefair
Winner, Best Large Studio
2018 London Design Awards
-
Goddard Littlefair
Winner, London’s Leading Luxury Interior Design Studio
Lux Magazine Leading Designers Award, 2018
-
The Garden
Winner, Biophilic Design
Client:
PrincipalRestaurant & Bar Design Awards, 2018
view project
-
The Garden
Winner, Restaurant Design
Client:
PrincipalSBID International Design Awards, 2018
view project
-
The Garden
Gold Winner, Interior Design – Hospitality
Client:
PrincipalLondon Design Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
5* Winner, Best Hotel Interior, Scotland
Client:
PrincipalInternational Property Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Winner, Hotel (Upscale)
Client:
PrincipalGold Key Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Silver Winner, Interior Design – Hospitality
Client:
PrincipalLondon Design Awards, 2018
view project
-
The Gleneagles Hotel
Winner, Hotel (Luxury)
Client:
EnnismoreHospitality Design Awards, 2018
view project
-
Hans’ Bar & Grill
Silver Winner, Interior Design – Hospitality
Client:
Cadogan EstateLondon Design Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Best Project 2018
Client:
PrincipalBest on Archilovers, 2018
view project
-
The Principal Edinburgh Charlotte Square
Highly Commended, Hospitality Project of the Year
Client:
PrincipalMixology Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Runner-up, Best use of decorative lighting in a hotel project
Client:
PrincipalDarc Decorative Awards, 2018
view project
-
The Gleneagles Hotel
Shortlisted, Public Spaces (Luxury)
Client:
EnnismoreHospitality Design Awards, 2018
view project
-
One Park Drive
Shortlisted, Best Interior Design: Development
Client:
Canary Wharf GroupSunday Times British Homes Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Shortlisted, Hotel
Client:
PrincipalFX Design Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Shortlisted, Hotel
Client:
PrincipalWIN Awards, 2018
view project
-
BABA
Shortlisted, Restaurant (Casual Dining)
Client:
PrincipalGold Key Awards, 2018
view project
-
BABA
Shortlisted, Interior Design – Hospitality
Client:
PrincipalLondon Design Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Shortlisted, Hotel Bedroom & Suites Design
Client:
PrincipalSBID International Design Awards, 2018
view project
-
The Principal Edinburgh Charlotte Square
Shortlisted, Architecture: Hotel Project
Client:
PrincipalScottish Design Awards, 2018
view project
-
The Gleneagles Hotel
Shortlisted, Architecture: Hotel Project
Client:
EnnismoreScottish Design Awards, 2018
view project
-
Goddard Littlefair
Winner, Best Design Studio – 20+
2017 London Design Awards
-
Goddard Littlefair
Winner, Interior Designer of the Year
2017 Build Awards
-
The Gleneagles Hotel
Gold Winner, Interior Design – Hospitality
Client:
EnnismoreLondon Design Awards, 2017
view project
-
One Park Drive
Gold Winner, Interior Design – Residential
Client:
Canary Wharf GroupLondon Design Awards, 2017
view project
-
The Principal York
Winner, Hotel of the Year
Client:
PrincipalVisit York Tourism Awards, 2017
view project
-
The Principal Edinburgh George Street
Winner, Hotel of the Year
Client:
PrincipalScottish Hotel Awards, 2017
view project
-
The Principal York
Winner, Best Hotel Interiors
Client:
PrincipalLate Rooms, Simply The Guest Awards, 2017
view project
-
The Principal Edinburgh George Street
Winner, Regional Awards – Best City Hotel
Client:
Principal HotelsScottish Hotel Awards, 2017
view project
-
The Principal York
Winner, Conference Venue of the Year
Client:
PrincipalVisit York Tourism Awards, 2017
view project
-
The Principal York
Winner, Best Conference / Exhibition Space
Client:
PrincipalCHS Awards, 2017
view project
-
The Principal York
Highly Commended, Best Bedroom
Client:
PrincipalCHS Awards, 2017
view project
-
One Stop Doctors
Highly Commended, Patient Environment
Client:
One Stop DoctorsBuilding Better Healthcare Awards, 2017
view project
-
The Gleneagles Hotel
Shortlisted, Lobby & Public Spaces
Client:
EnnismoreAHEAD Awards Europe, 2017
view project
-
The Gleneagles Hotel
Shortlisted, Suites
Client:
EnnismoreAHEAD Awards Europe, 2017
view project
-
One Stop Doctors
Shortlisted, Uk 2017 Project
Client:
One Stop DoctorsFX Design Awards, 2017
view project
-
One Stop Doctors
Shortlisted, Annual Public Space
Client:
One Stop DoctorsModern Decoration International Media Awards, 2017
view project
-
The Gleneagles Hotel
Shortlisted, Hotel Bedroom & Suite Design
Client:
EnnismoreSBID INTERNATIONAL DESIGN EXCELLENCE AWARDS, 2017
view project
-
One Stop Doctors
Shortlisted, Healthcare Design
Client:
One Stop DoctorsSBID INTERNATIONAL DESIGN EXCELLENCE AWARDS, 2017
view project
-
The Principal York
Shortlisted, Best Welcome Guest Experience
Client:
PrincipalCHS Awards, 2017
view project
-
The Principal York
Shortlisted, Best Luxury Hotel
Client:
PrincipalLate Rooms, Simply The Guest Awards, 2017
view project
-
The Garden Room, The Principal York
Shortlisted, Cafe or Tearoom of the Year
Client:
PrincipalVisit York Tourism Awards, 2017
view project
-
The Printing Press Bar & Kitchen
Winner, Restaurant or Bar in a Hotel
Client:
PrincipalRestaurant & Bar Design Awards, 2016
view project
-
The Principal Edinburgh
5* Winner, Best Hotel Interiors, Scotland
Client:
PrincipalInternational Property Awards 2016
view project
-
SOUTH BANK TOWER
GOLD WINNER, RESIDENTIAL INTERIORS
CLIENT:
CITLONDON DESIGN AWARDS 2016
view project
-
THE PRINCIPAL YORK
GOLD WINNER, HOSPITALITY INTERIORS
CLIENT:
PrincipalLONDON DESIGN AWARDS 2016
view project
-
The Principal York
Winner, Hotel of the Year
Client:
PrincipalVisit York
view project
Tourism Awards, 2016
-
The Principal York
Winner, Conference Venue of the Year
Client:
PrincipalVisit York
view project
Tourism Awards 2016
-
Hilton Budapest
Winner, Catering Facilities and Interior Design
Client:
Hilton HotelsGastro Design Awards, 2016
view project
-
THE PRINTING PRESS BAR & KITCHEN
SILVER WINNER, HOSPITALITY INTERIORS
CLIENT:
PRINCIPALLONDON DESIGN AWARDS 2016
view project
-
Hilton Budapest
Highly Commended, Hotel Interior Hungary
Client:
Hilton HotelsInternational Property Awards 2016
view project
-
The Principal York
Shortlisted, Interior Design: Lobby, Lounge & Public Areas
Client:
PrincipalEuropean Hotel Design Awards, 2016
view project
-
The Principal York
Shortlisted, Architecture: Renovation & Restoration
Client:
PrincipalEuropean Hotel Design Awards, 2016
view project
-
South Bank Tower
SHORTLISTED, Show Flats & Developments
CLIENT:
CITSBID INTERNATIONAL DESIGN EXCELLENCE AWARDS, 2016
view project
-
The Printing Press Bar & Kitchen
SHORTLISTED, Restaurant Design
Client:
PrincipalSBID International Design Excellence Awards, 2016
view project
-
Hilton Budapest
SHORTLISTED, Hotel Design
Client:
Hilton HotelsSBID International Design Excellence Awards, 2016
view project
-
Private Apartment, Belgravia
SHORTLISTED, Residential Design Under £1M
Client:
Private ClientSBID International Design Excellence Awards, 2016
view project
-
THE PRINCIPAL YORK
SHORTLISTED, BUSINESS TOURISM
CLIENT:
PRINCIPAL HOTELSWHITE ROSE AWARDS, 2016
view project
-
Ebury Square
Winner, Best Luxury Home
Client:
Berkeley Homes2015 London Evening Standard
view project
New Homes Awards
-
The Byfield
Winner, Best House Design (up to 50 homes)
Client:
St James GroupThe Sunday Times
view project
British Homes Awards 2015
-
Hilton Budapest
GOLD Winner, Hospitality Interiors
Client:
Hilton HotelsLondon Design Awards 2015
view project
-
Southbank Place Marketing Suite
SILVER Winner, Corporate Interiors
Client:
Canary Wharf Group & Qatari DiarLondon Design Awards 2015
view project
-
Private Apartment, Belgravia
SILVER Winner, Residential Interiors
Client:
Private ClientLondon Design Awards 2015
view project


SwiftECC
Contents:
- Usage
- Basics
- Creating New Keys
- Loading Existing Keys
- Encrypted Private Keys
- Encryption and Decryption
- AEAD Encryption and Decryption
- HPKE Encryption and Decryption
- Signing and Verifying
- Secret Key Agreement
- Creating New Domains
- Elliptic Curve Arithmetic
- Performance
- Dependencies
- References
- Acknowledgement
SwiftECC provides elliptic curve cryptography in Swift. This encompasses:
- Creating, loading and storing public and private keys
- Encryption and decryption using the ECIES algorithm based on the AES block cipher and six different block modes
- AEAD (Authenticated Encryption with Associated Data) encryption and decryption using the ECIES algorithm with the ChaCha20/Poly1305 or the AES/GCM cipher
- HPKE (Hybrid Public Key Encryption) encryption and decryption according to RFC 9180
- Signature signing and verifying using the ECDSA algorithm, including the option of deterministic signatures
- Secret key agreement using the Diffie-Hellman key agreement algorithm - ECDH
- Ability to create your own domains
- General elliptic curve arithmetic
Usage
In your project Package.swift file add a dependency like
dependencies: [
.package(url: "https://github.com/leif-ibsen/SwiftECC", from: "3.9.0"),
]
SwiftECC requires Swift 5.0. It also requires that the Int and UInt types be 64 bit types. SwiftECC uses Apple’s CryptoKit framework. Therefore, for macOS the version must be at least 10.15, for iOS the version must be at least 13, and for watchOS the version must be at least 8.
Basics
The basic concept in SwiftECC is the Elliptic Curve Domain, represented by the Domain class. Please, refer section 3.1 in [SEC 1] that describes the domain concept in detail.
There are 18 predefined NIST domains and 14 predefined Brainpool domains in SwiftECC, and it is possible to create your own characteristic 2, and odd prime characteristic domains.
You need a public key in order to encrypt a message or verify a signature, and you need a private key in order to decrypt a message or sign a message. Given a domain, you can generate public/private key pairs or you can load them from the PEM- or DER encoding of existing keys.
Creating New Keys
For a given domain it is possible to generate a public/private key pair. For example:
let domain = Domain.instance(curve: .EC384r1)
let (pubKey, privKey) = domain.generateKeyPair()
The private key is simply a random positive integer less than the domain order. The public key is the domain generator point multiplied by the private key. Given a private key, say ‘privKey’, you can generate the corresponding public key, like
let pubKey = ECPublicKey(privateKey: privKey)
Given a domain, say ‘dom’ and a curve point, say ‘pt’, you can generate a public key, like
let pubKey = try ECPublicKey(domain: dom, w: pt)
Loading Existing Keys
It is possible to create keys from their PEM encodings. For example
// Public key encoding - EC384r1 domain
let pubKeyPem =
"""
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEQW/MahMwMTFjwY95uOEdfBVC7HrQhTGG
TwxiPlgDiARqC6y6EQ1Ajkuhe4A02WOltRYQRXKytzspOR25UfgtagURAwxVFYzR
9cmi6FRmvvq/Tsigd/dAi4FNjniR7/Pg
-----END PUBLIC KEY-----
"""
let pubKey = try ECPublicKey(pem: pubKeyPem)
// Private key encoding in PKCS#8 format - EC384r1 domain
let privKeyPem =
"""
-----BEGIN PRIVATE KEY-----
MIG/AgEAMBAGByqGSM49AgEGBSuBBAAiBIGnMIGkAgEBBDBmpNziSYmGoWwl7apJ
M9ZdDBxkJqmxMScHGXG45ZQXSv7fIuJlsSwxK76nUiiO7gigBwYFK4EEACKhZANi
AARBb8xqEzAxMWPBj3m44R18FULsetCFMYZPDGI+WAOIBGoLrLoRDUCOS6F7gDTZ
Y6W1FhBFcrK3Oyk5HblR+C1qBREDDFUVjNH1yaLoVGa++r9OyKB390CLgU2OeJHv
8+A=
-----END PRIVATE KEY-----
"""
let privKey = try ECPrivateKey(pem: privKeyPem)
// See the key ASN1 structures
print(pubKey)
print(privKey)
giving:
Sequence (2):
Sequence (2):
Object Identifier: 1.2.840.10045.2.1
Object Identifier: <IP_ADDRESS>.34
Bit String (776): 00000100 01000001 01101111 11001100 01101010 00010011 00110000 00110001 00110001 01100011 11000001 10001111 01111001 10111000 11100001 00011101 01111100 00010101 01000010 11101100 01111010 11010000 10000101 00110001 10000110 01001111 00001100 01100010 00111110 01011000 00000011 10001000 00000100 01101010 00001011 10101100 10111010 00010001 00001101 01000000 10001110 01001011 10100001 01111011 10000000 00110100 11011001 01100011 10100101 10110101 00010110 00010000 01000101 01110010 10110010 10110111 00111011 00101001 00111001 00011101 10111001 01010001 11111000 00101101 01101010 00000101 00010001 00000011 00001100 01010101 00010101 10001100 11010001 11110101 11001001 10100010 11101000 01010100 01100110 10111110 11111010 10111111 01001110 11001000 10100000 01110111 11110111 01000000 10001011 10000001 01001101 10001110 01111000 10010001 11101111 11110011 11100000
Sequence (4):
Integer: 1
Octet String (48): 66 a4 dc e2 49 89 86 a1 6c 25 ed aa 49 33 d6 5d 0c 1c 64 26 a9 b1 31 27 07 19 71 b8 e5 94 17 4a fe df 22 e2 65 b1 2c 31 2b be a7 52 28 8e ee 08
[0]:
Object Identifier: <IP_ADDRESS>.34
[1]:
Bit String (776): 00000100 01000001 01101111 11001100 01101010 00010011 00110000 00110001 00110001 01100011 11000001 10001111 01111001 10111000 11100001 00011101 01111100 00010101 01000010 11101100 01111010 11010000 10000101 00110001 10000110 01001111 00001100 01100010 00111110 01011000 00000011 10001000 00000100 01101010 00001011 10101100 10111010 00010001 00001101 01000000 10001110 01001011 10100001 01111011 10000000 00110100 11011001 01100011 10100101 10110101 00010110 00010000 01000101 01110010 10110010 10110111 00111011 00101001 00111001 00011101 10111001 01010001 11111000 00101101 01101010 00000101 00010001 00000011 00001100 01010101 00010101 10001100 11010001 11110101 11001001 10100010 11101000 01010100 01100110 10111110 11111010 10111111 01001110 11001000 10100000 01110111 11110111 01000000 10001011 10000001 01001101 10001110 01111000 10010001 11101111 11110011 11100000
Encrypted Private Keys
Private keys can be encrypted as described in [PKCS#5] using the PBES2 scheme. For example:
let pw = Bytes("MySecret".utf8)
let domain = Domain.instance(curve: .EC384r1)
let (_, priv) = domain.makeKeyPair()
let encryptedKey = priv.pemEncrypted(password: pw, cipher: .AES256)
print(encryptedKey)
giving (for example):
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBHjBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI3id2VFlFxXUCAggA
MB0GCWCGSAFlAwQBKgQQlJJQtcZ23p1Q4fXmvpS6hgSB0DBuxL/sCUc/c9NDhrHK
/R2sbtS7rs5a9zUFwcMNV1nVUCK1SSbaCg8/BxHPfqKlAw4RcnsQtN+YD7hz5pxF
YDcYk4mEZo7ODFkRxhKF7vLsUsRZAl2XYGIJflp03+fAWdsiNisjo/4Y/5xxWvCe
OBzfjRpsDT4HjRgcxTtxrzvInzrJkQwyDBAkPMudIshkPOQ1LEoXhi0gVFl9jGN+
eSLv5Wba2chf/kQcw7R4B3iiE5787wE2fWvvh4ek3oSYcLCvO/gkwgUhyA2hk3rn
01k=
-----END ENCRYPTED PRIVATE KEY-----
The implied encryption parameters are cipher block mode = CBC, iteration count = 2048 and salt = 8 random bytes. The password is simply a byte array, any possible interpretation of it as a string is unspecified. The encrypted private key is compatible with, and is readable by OpenSSL.
Private keys can be created from their PEM encodings in encrypted form. In the example the encrypted private key was created by OpenSSL using the AES-256 cipher in CBC mode with password ‘abcd’.
let encryptedPem =
"""
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIHeMEkGCSqGSIb3DQEFDTA8MBsGCSqGSIb3DQEFDDAOBAg7pgGVDlE/xgICCAAw
HQYJYIZIAWUDBAEqBBCFF4KWxWqhOB5Q8dOwdcPkBIGQbuj2TvlhtpMZ3ZhLBBBx
kJfY1l09yNcJNEcvS8RX4/STXZkt5gMBgtY2DvGAKI0wkpbim+kXSjM6/hmNxY5b
jhQapm8l8jbVGkETtYfseZXpvIT5lnBy9KtO8o3OmlRTV3xXu3KeDZakDoimfQ8G
N7SldmFRcz171yMoIQ17ZU95uneZoogsRuMVMVUJXEh7
-----END ENCRYPTED PRIVATE KEY-----
"""
let privKey = try ECPrivateKey(pem: encryptedPem, password: Bytes("abcd".utf8))
print(privKey)
giving:
Sequence (4):
Integer: 1
Octet String (32): 1e 4d c5 de 0f 47 66 6b 7e 4c b8 ee e5 0f f9 6c 4a d3 4f 6f 2e 07 f7 fc e7 c8 24 dd 17 18 fd fa
[0]:
Object Identifier: 1.2.840.10<IP_ADDRESS>
[1]:
Bit String (520): 00000100 00101110 10100100 10110110 10001111 11111010 00111111 00000111 01011010 01011101 01110000 01100001 10110000 10101110 01011010 10011100 10001111 00110100 11010000 11111101 10010110 11001110 00101011 10001111 11000001 10101001 11000000 00001101 00011101 11011101 11001011 10101110 10011000 11001011 10000101 01110001 10100010 11100000 01100011 01101010 11110100 11011101 00011000 01011101 10010110 01010101 10110011 00101101 01010000 10100010 00110001 10000100 11011001 00111001 00011000 01100100 10001110 11011111 10011100 00010100 10110101 11011010 00111010 10101100 11111100
SwiftECC can read encrypted private key files provided they were encrypted with one of the ciphers AES-128, AES-192 or AES-256 in CBC mode.
Encryption and Decryption
Encryption and decryption is done using the ECIES algorithm based on the AES block cipher using one of
AES-128, AES-192 or AES-256 ciphers, depending on your choice.
The following cipher block modes are supported:
- GCM - Galois Counter mode. This is the default mode
- ECB - Electronic Codebook mode with PKCS#7 padding
- CBC - Cipher Block Chaining mode with PKCS#7 padding
- CFB - Cipher Feedback mode
- CTR - Counter mode
- OFB - Output Feedback mode
The encryption and decryption speed for domain EC256k1 (the bitcoin domain) measured on an iMac 2021, Apple M1 chip using AES-128 are shown below - units are Megabytes per second.
| Block Mode | Encrypt | Decrypt |
|---|---|---|
| GCM | 53 MByte/Sec | 53 MByte/Sec |
| ECB | 30 MByte/Sec | 30 MByte/Sec |
| CBC | 24 MByte/Sec | 25 MByte/Sec |
| CFB | 23 MByte/Sec | 23 MByte/Sec |
| CTR | 30 MByte/Sec | 30 MByte/Sec |
| OFB | 29 MByte/Sec | 29 MByte/Sec |
Unless compatibility with IBM’s BlueECC product is necessary, encryption / decryption using GCM block mode is deprecated. Use the encryptAESGCM / decryptAESGCM methods instead. Their performance is many times better.
Key Derivation
SwiftECC uses the X9.63 Key Derivation Function to derive block cipher keying materiel. Please refer [SEC 1] section 3.6. Six cases are considered:
AES-128/GCM block mode
KDF generates 32 bytes.
AES encryption/decryption key = bytes 0 ..< 16
Nonce = bytes 16 ..< 32
AES-192/GCM block mode
KDF generates 40 bytes.
AES encryption/decryption key = bytes 0 ..< 24
Nonce = bytes 24 ..< 40
AES-256/GCM block mode
KDF generates 48 bytes.
AES encryption/decryption key = bytes 0 ..< 32
Nonce = bytes 32 ..< 48
AES-128/Non-GCM block mode
KDF generates 48 bytes.
AES encryption/decryption key = bytes 0 ..< 16
HMAC key = bytes 16 ..< 48
AES-192/Non-GCM block mode
KDF generates 56 bytes.
AES encryption/decryption key = bytes 0 ..< 24
HMAC key = bytes 24 ..< 56
AES-256/Non-GCM block mode
KDF generates 64 bytes.
AES encryption/decryption key = bytes 0 ..< 32
HMAC key = bytes 32 ..< 64
The AES key and HMAC key can be retrieved with the ECPrivateKey method ‘getKeyAndMac’.
For block modes CBC, CFB, CTR, and OFB the initialization vector (IV) is 16 zero bytes.
BlueECC Compatibility
Data encrypted by SwiftECC in the EC256r1 domain with AES128/GCM, in the EC384r1 domain with AES256/GCM and in the EC521r1 domain with AES256/GCM can be decrypted with IBM’s BlueECC product using curve prime256v1, secp384r1, and secp521r1, respectively. Likewise, data encrypted by BlueECC with curve prime256v1, secp384r1 and secp521, can be decrypted by SwiftECC using EC256r1 with AES128/GCM, EC384r1 with AES256/GCM and EC521r1 with AES256/GCM, respectively.
Example
import SwiftECC
// You need a public key to encrypt a message and the corresponding private key to decrypt it,
// for example from the EC163k1 domain
let pemPublic163k1 =
"""
-----BEGIN PUBLIC KEY-----
MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEA6txn7CCae0d9AiGj3Rk5m9XflTCB81oe1fKZi4F4oip
SF2u79k8TD5J
-----END PUBLIC KEY-----
"""
let pemPrivate163k1 =
"""
-----BEGIN EC PRIVATE KEY-----
MFICAQEEFNfflqz2oOd9WpxuMZ9wJTFO1sjgoAcGBSuBBAABoS4DLAAEA6txn7CCae0d9AiGj3Rk
5m9XflTCB81oe1fKZi4F4oipSF2u79k8TD5J
-----END EC PRIVATE KEY-----
"""
let text = "The quick brown fox jumps over the lazy dog!"
do {
let pubKey = try ECPublicKey(pem: pemPublic163k1)
let privKey = try ECPrivateKey(pem: pemPrivate163k1)
let encryptedData = pubKey.encrypt(msg: text.data(using: .utf8)!, cipher: .AES128)
let decryptedData = try privKey.decrypt(msg: encryptedData, cipher: .AES128)
print(String(data: decryptedData, encoding: .utf8)!)
} catch {
print("\(error)")
}
giving
The quick brown fox jumps over the lazy dog!
AEAD Encryption and Decryption
Authenticated Encryption with Associated Data (AEAD) is implemented with the ChaCha20/Poly1305 algorithm and the AES/GCM algorithm. Both implementations use Apple’s CryptoKit framework, that takes advantage of hardware support for the AES and GCM algorithms.
Example
import SwiftECC
let plainText = "Hi, there!"
let aaData = "This is the additional authenticated data"
let (pub, priv) = Domain.instance(curve: .EC256k1).makeKeyPair()
let cipherText1 = pub.encryptChaCha(msg: Bytes(plainText.utf8), aad: Bytes(aaData.utf8))
let cipherText2 = pub.encryptAESGCM(msg: Bytes(plainText.utf8), cipher: .AES128, aad: Bytes(aaData.utf8))
do {
let text1 = try priv.decryptChaCha(msg: cipherText1, aad: Bytes(aaData.utf8))
print(String(bytes: text1, encoding: .utf8)!)
let text2 = try priv.decryptAESGCM(msg: cipherText2, cipher: .AES128, aad: Bytes(aaData.utf8))
print(String(bytes: text2, encoding: .utf8)!)
} catch {
print("Exception: \(error)")
}
giving:
Hi, there!
Hi, there!
The encryption and decryption speed for domain EC256k1 (the bitcoin domain) measured on an iMac 2021, Apple M1 chip are shown below - units are Megabytes per second.
| Algorithm | Encrypt | Decrypt |
|---|---|---|
| ChaCha20/Poly1305 | 500 MByte/Sec | 425 MByte/Sec |
| AES-128/GCM | 2000 MByte/Sec | 1200 MByte/Sec |
Key Derivation
SwiftECC uses the X9.63 Key Derivation Function to derive block cipher keying materiel. Please refer [SEC 1] section 3.6. Four cases are considered:
ChaCha20/Poly1305
KDF generates 44 bytes.
Encryption/decryption key = bytes 0 ..< 32
Nonce = bytes 32 ..< 44
AES-128/GCM
KDF generates 28 bytes.
AES encryption/decryption key = bytes 0 ..< 16
Nonce = bytes 16 ..< 28
AES-192/GCM
KDF generates 36 bytes.
AES encryption/decryption key = bytes 0 ..< 24
Nonce = bytes 24 ..< 36
AES-256/GCM
KDF generates 44 bytes.
AES encryption/decryption key = bytes 0 ..< 32
Nonce = bytes 32 ..< 44
HPKE Encryption and Decryption
SwiftECC contains an implementation of the new Hybrid Public Key Encryption (HPKE) standard defined in RFC 9180. It operates with the concepts of a sender and a recipient. A sender encrypts (or seals) cleartext messages intended for a given recipient, and a recipient decrypts (or opens) the resulting ciphertext messages. A sender is represented by the Sender class, and a recipient is represented by the Recipient class. Using them, you can:
- Create a CipherSuite consisting of a Key Encapsulation Mechanism (KEM), a Key Derivation Function (KDF) and a AEAD Encryption Algorithm (AEAD)
- The CipherSuite can encrypt a single plain text message or decrypt a single ciphertext
- You can create a Sender instance based on a CipherSuite and use it to encrypt a sequence of plaintext messages
- You can create a Recipient instance based on a CipherSuite and use it to decrypt a sequence of ciphertexts
Example 1
// Encryption and decryption of a single message in base mode
import SwiftECC
do {
let plainText = Bytes("Hi, there".utf8)
let suite1 = CipherSuite(kem: .X448, kdf: .KDF512, aead: .AESGCM256)
let (recipientPub, recipientPriv) = try suite1.makeKeyPair()
let (encapsulatedKey, cipherText) = try suite1.seal(publicKey: recipientPub, info: [1, 2, 3], pt: plainText, aad: [4, 5, 6])
let decrypted = try suite1.open(privateKey: recipientPriv, info: [1, 2, 3], ct: cipherText, aad: [4, 5, 6], encap: encapsulatedKey)
print(String(bytes: decrypted, encoding: .utf8)!)
} catch {
print("Exception: \(error)")
}
giving:
Hi, there
Example 2
// Encryption and decryption of several messages in authenticated mode
import SwiftECC
do {
let plainText1 = Bytes("Hi, there 1".utf8)
let plainText2 = Bytes("Hi, there 2".utf8)
let plainText3 = Bytes("Hi, there 3".utf8)
let suite2 = CipherSuite(kem: .P384, kdf: .KDF384, aead: .CHACHAPOLY)
let (senderPub, senderPriv) = try suite2.makeKeyPair()
let (recipientPub, recipientPriv) = try suite2.makeKeyPair()
let sender = try Sender(suite: suite2, publicKey: recipientPub, info: [1, 2, 3], authentication: senderPriv)
let cipherText1 = try sender.seal(pt: plainText1, aad: [4, 5])
let cipherText2 = try sender.seal(pt: plainText2, aad: [6, 7])
let cipherText3 = try sender.seal(pt: plainText3, aad: [])
let recipient = try Recipient(suite: suite2, privateKey: recipientPriv, info: [1, 2, 3], authentication: senderPub, encap: sender.encapsulatedKey)
let decrypted1 = try recipient.open(ct: cipherText1, aad: [4, 5])
let decrypted2 = try recipient.open(ct: cipherText2, aad: [6, 7])
let decrypted3 = try recipient.open(ct: cipherText3, aad: [])
print(String(bytes: decrypted1, encoding: .utf8)!)
print(String(bytes: decrypted2, encoding: .utf8)!)
print(String(bytes: decrypted3, encoding: .utf8)!)
} catch {
print("Exception: \(error)")
}
giving:
Hi, there 1
Hi, there 2
Hi, there 3
Signing and Verifying
Signing data and verifying signatures is performed using the ECDSA algorithm. It is possible to generate deterministic signatures as specified in [RFC-6979] by setting the deterministic parameter to true in the sign operation.
The message digest used in the process is determined from the domain field size as follows:
- field size <= 224: SHA2-224
- 224 < field size <= 256: SHA2-256
- 256 < field size <= 384: SHA2-384
- 384 < field size: SHA2-512
BlueECC Compatibility
Signatures created by SwiftECC in the EC256r1, EC384r1 and EC521r1 domains can be verified by IBM’s BlueECC product using curve prime256v1, secp384r1 and secp521r1, respectively. Likewise, signatures created by BlueECC with one of the curves prime256v1, secp384r1 and secp521r1 can be verified by SwiftECC using domains EC256r1, EC384r1 and EC521r1, respectively.
CryptoKit Compatibility
Signatures created by SwiftECC in the EC256r1, EC384r1 and EC521r1 domains can be verified by Swift CryptoKit using curve P256, P384 and P521, respectively. Likewise, signatures created by Swift CryptoKit with one of the curves P256, P384 and P521 can be verified by SwiftECC using domains EC256r1, EC384r1 and EC521r1, respectively.
Example
import SwiftECC
// Get a predefined domain - for example brainpool BP160r1
let domain = Domain.instance(curve: .BP160r1)
// Create your own keys
let (pubKey, privKey) = domain.makeKeyPair()
// See how they look
print(pubKey.asn1)
print(privKey.asn1)
// Store them in PEM format for future use
let pubPEM = pubKey.pem
let privPEM = privKey.pem
let message = "The quick brown fox jumps over the lazy dog!".data(using: .utf8)!
let sig = privKey.sign(msg: message)
let ok = pubKey.verify(signature: sig, msg: message)
print("Signature is", ok ? "good" : "wrong")
giving (for example):
Sequence (2):
Sequence (2):
Object Identifier: 1.2.840.10045.2.1
Object Identifier: <IP_ADDRESS>.<IP_ADDRESS>.1.1
Bit String (328): 00000100 00000011 00000111 00110011 01010100 00000001 10111100 01101111 10100001 01001000 11101000 01111100 10001111 00000110 00010010 11100111 11111010 10010001 00100100 01001000 11000110 01110001 00110100 01001000 10011110 01011110 11000000 10010001 01000110 01011010 01001110 01110000 00011011 01010111 10101011 01101010 00011011 01101100 01100100 01000100 01111101
Sequence (4):
Integer: 1
Octet String (20): 32 96 e0 c4 d7 f5 cb 03 0c 95 63 b1 a2 c1 2f 64 4c dc d6 4c
[0]:
Object Identifier: <IP_ADDRESS>.<IP_ADDRESS>.1.1
[1]:
Bit String (328): 00000100 00000011 00000111 00110011 01010100 00000001 10111100 01101111 10100001 01001000 11101000 01111100 10001111 00000110 00010010 11100111 11111010 10010001 00100100 01001000 11000110 01110001 00110100 01001000 10011110 01011110 11000000 10010001 01000110 01011010 01001110 01110000 00011011 01010111 10101011 01101010 00011011 01101100 01100100 01000100 01111101
Signature is good
Secret Key Agreement
Given your own private key and another party’s public key, you can generate a byte array that can be used as a symmetric encryption key.
The other party can generate the same byte array by using his own private key and your public key.
SwiftECC supports three mechanisms:
- The basic Diffie-Hellman primitive
- The X9.63 version specified in [SEC 1] section 3.6.1
- The HKDF version specified in [RFC-5869]
Basic Diffie-Hellman Example
import SwiftECC
do {
let domain = Domain.instance(curve: .EC256r1)
// Party A's keys
let (pubA, privA) = domain.makeKeyPair()
// Party B's keys
let (pubB, privB) = domain.makeKeyPair()
let secretA = try privA.sharedSecret(pubKey: pubB)
let secretB = try privB.sharedSecret(pubKey: pubA)
print(secretA)
print(secretB)
} catch {
print("Exception: \(error)")
}
giving (for example):
[44, 218, 188, 109, 139, 24, 227, 22, 116, 197, 147, 194, 138, 107, 105, 11, 236, 67, 236, 110, 42, 26, 250, 151, 111, 236, 60, 98, 210, 121, 243, 44]
[44, 218, 188, 109, 139, 24, 227, 22, 116, 197, 147, 194, 138, 107, 105, 11, 236, 67, 236, 110, 42, 26, 250, 151, 111, 236, 60, 98, 210, 121, 243, 44]
X9.63 Example
import SwiftECC
do {
let domain = Domain.instance(curve: .EC256r1)
// Party A's keys
let (pubA, privA) = domain.makeKeyPair()
// Party B's keys
let (pubB, privB) = domain.makeKeyPair()
let info: Bytes = [1, 2, 3]
let secretA = try privA.x963KeyAgreement(pubKey: pubB, length: 16, md: .SHA2_256, sharedInfo: info)
let secretB = try privB.x963KeyAgreement(pubKey: pubA, length: 16, md: .SHA2_256, sharedInfo: info)
print(secretA)
print(secretB)
} catch {
print("Exception: \(error)")
}
giving (for example):
[92, 161, 137, 44, 47, 30, 6, 26, 43, 183, 199, 130, 19, 254, 232, 106]
[92, 161, 137, 44, 47, 30, 6, 26, 43, 183, 199, 130, 19, 254, 232, 106]
For the key agreement to work, the two parties must agree on which domain, which message digest and which shared information (possibly none) to use.
HKDF Example
import SwiftECC
do {
let domain = Domain.instance(curve: .EC256r1)
// Party A's keys
let (pubA, privA) = domain.makeKeyPair()
// Party B's keys
let (pubB, privB) = domain.makeKeyPair()
let info: Bytes = [1, 2, 3]
let salt: Bytes = [4, 5, 6]
let secretA = try privA.hkdfKeyAgreement(pubKey: pubB, length: 16, md: .SHA2_256, sharedInfo: info, salt: salt)
let secretB = try privB.hkdfKeyAgreement(pubKey: pubA, length: 16, md: .SHA2_256, sharedInfo: info, salt: salt)
print(secretA)
print(secretB)
} catch {
print("Exception: \(error)")
}
giving (for example):
[202, 36, 31, 96, 207, 220, 135, 77, 130, 41, 214, 139, 214, 30, 106, 180]
[202, 36, 31, 96, 207, 220, 135, 77, 130, 41, 214, 139, 214, 30, 106, 180]
For the key agreement to work, the two parties must agree on which domain, which message digest, which shared information (possibly none) and which salt (possibly none) to use.
CryptoKit Compatibility
SwiftECC key agreement is compatible with Swift CryptoKit key agreement
in that the EC256r1, EC384r1 and EC521r1 domains correspond to CryptoKit’s P256, P384 and P521 curves,
and the SHA2_256, SHA2_384 and SHA2_512 message digests correspond to CryptoKit’s SHA256, SHA384 and SHA512 message digests.
- The sharedSecret method corresponds to the CryptoKit method sharedSecretFromKeyAgreement
- The x963KeyAgreement method corresponds to the CryptoKit method x963DerivedSymmetricKey
- The hkdfKeyAgreement method corresponds to the CryptoKit method hkdfDerivedSymmetricKey
To convert CryptoKit keys - e.g. ckPubKey, ckPrivKey - to the corresponding SwiftECC keys:
let eccPubKey = try ECPublicKey(pem: ckPubKey.pemRepresentation)
let eccPrivKey = try ECPrivateKey(pem: ckPrivKey.pemRepresentation)
To convert SwiftECC keys - e.g. eccPubKey, eccPrivKey - to the corresponding CryptoKit keys:
let ckPubKey = try P256.KeyAgreement.PublicKey(pemRepresentation: eccPubKey.pem)
let ckPrivKey = try P256.KeyAgreement.PrivateKey(pemRepresentation: eccPrivKey.pem)
Creating New Domains
You can create your own domains as illustrated by the two examples below.
Example
This is example 3.5 from [GUIDE]. It shows how to make your own prime characteristic domain.
import SwiftECC
import BigInt
// Create the domain
let domain = try Domain.instance(name: "EC29", p: BInt(29), a: BInt(4), b: BInt(20), gx: BInt(1), gy: BInt(5), order: BInt(37), cofactor: 1)
let p1 = Point(BInt(5), BInt(22))
let p2 = Point(BInt(16), BInt(27))
print("p1 + p2 =", try domain.addPoints(p1, p2))
print("p1 * 2 =", try domain.multiplyPoint(p1, BInt(2)))
// Inspect the domain - please refer [SEC 1] appendix C.2
print(domain.asn1Explicit())
giving
p1 + p2 = Point(13, 6)
p1 * 2 = Point(14, 6)
Sequence (6):
Integer: 1
Sequence (2):
Object Identifier: 1.2.840.10045.1.1
Integer: 29
Sequence (2):
Octet String (1): 04
Octet String (1): 14
Octet String (3): 04 01 05
Integer: 37
Integer: 1
Example
This is example 3.6 from [GUIDE]. It shows how to make your own characteristic 2 domain.
import SwiftECC
import BigInt
// Reduction polynomial for x^4 + x^1 + 1
let rp = RP(4, 1)
// Create the domain
let domain = try Domain.instance(name: "EC4", rp: rp, a: BInt(8), b: BInt(9), gx: BInt(1), gy: BInt(1), order: BInt(22), cofactor: 2)
let p1 = Point(BInt(2), BInt(15))
let p2 = Point(BInt(12), BInt(12))
print("p1 + p2 =", try domain.addPoints(p1, p2))
print("p1 * 2 =", try domain.multiplyPoint(p1, BInt(2)))
// Inspect the domain - please refer [SEC 1] appendix C.2
print(domain.asn1Explicit())
giving
p1 + p2 = Point(1, 1)
p1 * 2 = Point(11, 2)
Sequence (6):
Integer: 1
Sequence (2):
Object Identifier: 1.2.840.10045.1.2
Sequence (2):
Integer: 4
Integer: 1
Sequence (2):
Octet String (1): 08
Octet String (1): 09
Octet String (3): 04 01 01
Integer: 22
Integer: 2
Elliptic Curve Arithmetic
SwiftECC implements the common elliptic curve arithmetic operations:
- Point multiplication
- Point addition
- Point doubling
- Point subtraction
- Point negation
- Is Point on curve?
It is also possible to encode curve points in either compressed- or uncompressed format, as well as to do the reverse decoding.
Performance
To assess the performance of SwiftECC, the signature generation and verification time and the keypair generation time was measured on an iMac 2021, Apple M1 chip. The results are shown in the table below - units are milliseconds. The columns mean:
- Sign: The time it takes to sign a short message
- Verify: The time it takes to verify a signature for a short message
- Keypair Generation: The time it takes to generate a public/private keypair
| Curve | Sign | Verify | Keypair Generation |
|---|---|---|---|
| brainpoolP160r1 | 0.7 mSec | 1.3 mSec | 2.9 mSec |
| brainpoolP160t1 | 0.7 mSec | 1.4 mSec | 2.9 mSec |
| brainpoolP192r1 | 0.96 mSec | 1.8 mSec | 3.9 mSec |
| brainpoolP192t1 | 0.96 mSec | 1.9 mSec | 3.9 mSec |
| brainpoolP224r1 | 1.3 mSec | 2.6 mSec | 5.7 mSec |
| brainpoolP224t1 | 1.3 mSec | 2.6 mSec | 5.7 mSec |
| brainpoolP256r1 | 1.7 mSec | 3.3 mSec | 7.4 mSec |
| brainpoolP256t1 | 1.7 mSec | 3.3 mSec | 7.4 mSec |
| brainpoolP320r1 | 2.9 mSec | 5.7 mSec | 13 mSec |
| brainpoolP320t1 | 2.9 mSec | 5.5 mSec | 13 mSec |
| brainpoolP384r1 | 4.5 mSec | 8.6 mSec | 21 mSec |
| brainpoolP384t1 | 4.4 mSec | 8.7 mSec | 21 mSec |
| brainpoolP512r1 | 9.2 mSec | 19 mSec | 44 mSec |
| brainpoolP512t1 | 9.3 mSec | 18 mSec | 44 mSec |
| secp192k1 | 0.96 mSec | 1.8 mSec | 4.0 mSec |
| secp192r1 | 0.96 mSec | 1.9 mSec | 3.9 mSec |
| secp224k1 | 1.3 mSec | 2.6 mSec | 5.8 mSec |
| secp224r1 | 1.3 mSec | 2.6 mSec | 5.7 mSec |
| secp256k1 | 1.7 mSec | 3.2 mSec | 7.4 mSec |
| secp256r1 | 1.7 mSec | 3.3 mSec | 7.5 mSec |
| secp384r1 | 4.5 mSec | 8.9 mSec | 21 mSec |
| secp521r1 | 9.8 mSec | 19 mSec | 47 mSec |
| sect163k1 | 1.2 mSec | 2.2 mSec | 5.1 mSec |
| sect163r2 | 1.2 mSec | 2.3 mSec | 5.1 mSec |
| sect233k1 | 2.3 mSec | 4.5 mSec | 11 mSec |
| sect233r1 | 2.3 mSec | 4.5 mSec | 11 mSec |
| sect283k1 | 3.5 mSec | 7.0 mSec | 17 mSec |
| sect283r1 | 3.5 mSec | 7.1 mSec | 17 mSec |
| sect409k1 | 8.0 mSec | 16 mSec | 41 mSec |
| sect409r1 | 8.0 mSec | 16 mSec | 42 mSec |
| sect571k1 | 17 mSec | 35 mSec | 92 mSec |
| sect571r1 | 17 mSec | 34 mSec | 92 mSec |
Dependencies
The SwiftECC package depends on the ASN1 and BigInt packages
dependencies: [
.package(url: "https://github.com/leif-ibsen/ASN1", from: "2.1.0"),
.package(url: "https://github.com/leif-ibsen/BigInt", from: "1.13.0"),
],
References
Algorithms from the following books and papers have been used in the implementation. There are references in the source code where appropriate.
- [FIPS 180-4] - FIPS PUB 180-4 - Secure Hash Standard (SHS), August 2015
- [GCM] - The Galois/Counter Mode of Operation (GCM)
- [GUIDE] - Hankerson, Menezes, Vanstone: Guide to Elliptic Curve Cryptography. Springer 2004
- [KNUTH] - Donald E. Knuth: Seminumerical Algorithms. Addison-Wesley 1971
- [NIST] - NIST Special Publication 800-38D, November 2007
- [PKCS#5] - Password-Based Cryptography Specification - Version 2.0, September 2000
- [RFC-5869] - HMAC-based Extract-and-Expand Key Derivation Function (HKDF), May 2010
- [RFC-6979] - Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA), August 2013
- [RFC-9180] - Hybrid Public Key Encryption, February 2022
- [SAVACS] - E. Savacs, C.K. Koc: The Montgomery Modular Inverse - Revisited, July 2000
- [SEC 1] - Standards for Efficient Cryptography 1 (SEC 1), Certicom Corp. 2009
- [SEC 2] - Standards for Efficient Cryptography 2 (SEC 2), Certicom Corp. 2010
- [WARREN] - Henry S. Warren, Jr.: Montgomery Multiplication, July 2012
- [X9.62] - X9.62 - Public Key Cryptography For The Financial Services Industry, 1998
Acknowledgement
The AES block cipher implementation is essentially a translation to Swift of the Go Language implementation of AES.


Interface SpeechRecognitionResultOrBuilder
{% verbatim %}public interface SpeechRecognitionResultOrBuilder extends MessageOrBuilder
Implements
com.google.protobuf.MessageOrBuilderMethods
getAlternatives(int index)
public abstract SpeechRecognitionAlternative getAlternatives(int index)
May contain one or more recognition hypotheses (up to the
maximum specified in `max_alternatives`).
These alternatives are ordered in terms of accuracy, with the top (first)
alternative being the most probable, as ranked by the recognizer.
repeated .google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative alternatives = 1;
| Type | Name | Description |
|---|---|---|
| int | index |
| Type | Description |
|---|---|
| SpeechRecognitionAlternative |
getAlternativesCount()
public abstract int getAlternativesCount()
May contain one or more recognition hypotheses (up to the
maximum specified in `max_alternatives`).
These alternatives are ordered in terms of accuracy, with the top (first)
alternative being the most probable, as ranked by the recognizer.
repeated .google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative alternatives = 1;
| Type | Description |
|---|---|
| int |
getAlternativesList()
public abstract List<SpeechRecognitionAlternative> getAlternativesList()
May contain one or more recognition hypotheses (up to the
maximum specified in `max_alternatives`).
These alternatives are ordered in terms of accuracy, with the top (first)
alternative being the most probable, as ranked by the recognizer.
repeated .google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative alternatives = 1;
| Type | Description |
|---|---|
| java.util.List<SpeechRecognitionAlternative> |
getAlternativesOrBuilder(int index)
public abstract SpeechRecognitionAlternativeOrBuilder getAlternativesOrBuilder(int index)
May contain one or more recognition hypotheses (up to the
maximum specified in `max_alternatives`).
These alternatives are ordered in terms of accuracy, with the top (first)
alternative being the most probable, as ranked by the recognizer.
repeated .google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative alternatives = 1;
| Type | Name | Description |
|---|---|---|
| int | index |
| Type | Description |
|---|---|
| SpeechRecognitionAlternativeOrBuilder |
getAlternativesOrBuilderList()
public abstract List<? extends SpeechRecognitionAlternativeOrBuilder> getAlternativesOrBuilderList()
May contain one or more recognition hypotheses (up to the
maximum specified in `max_alternatives`).
These alternatives are ordered in terms of accuracy, with the top (first)
alternative being the most probable, as ranked by the recognizer.
repeated .google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative alternatives = 1;
| Type | Description |
|---|---|
| java.util.List<? extends com.google.cloud.speech.v1p1beta1.SpeechRecognitionAlternativeOrBuilder> |
getChannelTag()
public abstract int getChannelTag()
For multi-channel audio, this is the channel number corresponding to the
recognized result for the audio from that channel.
For audio_channel_count = N, its output values can range from '1' to 'N'.
int32 channel_tag = 2;
| Type | Description |
|---|---|
| int | The channelTag. |
getLanguageCode()
public abstract String getLanguageCode()
Output only. The [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
language tag of the language in this result. This language code was
detected to have the most likelihood of being spoken in the audio.
string language_code = 5 [(.google.api.field_behavior) = OUTPUT_ONLY];
| Type | Description |
|---|---|
| java.lang.String | The languageCode. |
getLanguageCodeBytes()
public abstract ByteString getLanguageCodeBytes()
Output only. The [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
language tag of the language in this result. This language code was
detected to have the most likelihood of being spoken in the audio.
string language_code = 5 [(.google.api.field_behavior) = OUTPUT_ONLY];
| Type | Description |
|---|---|
| com.google.protobuf.ByteString | The bytes for languageCode. |
Implements
com.google.protobuf.MessageOrBuilder


Explain what makes cyberbullying different from other aggressive acts
Identify the harmful effects of cyber-attacks
Describe what upstanders can do to build a strong digital community
Know your rights and how to defend yourself and others
Now it’s time to learn more about cyberbullying. First, let’s begin by watching a brief clip about Kimberly.
Pay close attention to what is happening to Kimberly in this situation and how the girls are acting.
You see three girls laughing together in the hallway. In the background, a girl named Kimberly stands by her locker alone.
As you watch, think about what the problem is in the story and what you think could be a solution.
One of the three girls sends a message from her phone. The girls begin laughing and look over at Kimberly.
Kimberly first looks excited to receive the text as she reaches into her locker.
But as soon as she reads the message, her face changes. She does not look happy.
Kimberly looks up and notices that the three girls are laughing.
As Kimberly becomes more embarrassed and disappointed, the girls laugh even harder.
Now, let’s break it down and discuss this scene.
1. How can you use The ACID Test to identify this as bullying?
Click for hints
A
Aggressive - While we can’t read the text, it looks like the girls are texting Kimberly something mean or cruel to make fun of her and put her down.
C
Continual - While the text is instantaneous, cyberbullying is active and can happen 24/7 at any time or place. Kimberly receives her text during school.
I
Imbalance of power - Three girls appear to be ganging up on Kimberly. Because she is outnumbered three to one, this looks like a power imbalance.
D
Deliberate - The girls intentionally text Kimberly, showing that they are targeting her directly.
2. Why might the girls use cyberbullying over other forms of bullying to bully Kimberly?
Click for hints
?
Although in this situation, the girls are across the hall from Kimberly, their use of cyberbullying can allow them to act anonymously, seemingly free from consequences or punishment.
?
While we can’t tell if the girls posted on Facebook or Snapchat, or if they just sent a message, but we do know that they can reach lots of people. The message can be quickly and widely circulated to many other internet users, increasing the number of targets and bystanders involved.
3. Why might Kimberly be more harmed by cyberbullying?Click for hints
?
Because of the viral nature of bullying, Kimberly might be affected over time. The harm can live forever in cyberspace affecting her future reputation. What are some of the ways this might affect Kimberly’s future?
?
It’s very easy to be anonymous on the internet. The girls bullying Kimberly can be more cruel online in a way they never would be in real life.
4. What do you know now that might help to address bullying in Kimberly’s situation? What research helps to support this?Click for hints
?
There are a number of tools and tips for how you can respond in a cyberbullying situation. Think of some ways that you might help Kimberly in this situation.
?
The roles in the bullying cycle can change as environment or situations change. Now that you’ve put the ACID test to use to identify cyberbullying, you can be more aware of how to call it out.
5. Journal question
If you saw Kimberly bullied on Snapchat or Instagram, how could you use social media to help her?
Behind the Scenes
Learning Checklist
Connect with the feelings, thoughts and wishes of others
Let's to do some role playing to see what it’s like to be Kimberly, the upstander, and the bystander.
There are no right or wrong ways to act out these characters, just answer the questions as you think the character might answer them.
Before, during, and after this activity, take a moment and reflect on what’s happening in your body. Use your BAND.
Breathe Attention to your breath Notice any feelings, emotions, or stray thoughts you may be having Direct your attention back to your breath
You’ve played the characters. Now let’s learn some more about Kimberly so we can understand what she is thinking and feeling, and why her friends might be acting the way they are.
Kimberly Seymour used to be friends with the three girls who send her
cruel
Cruel: (adjective) Willfully causing pain or suffering to others, or feeling no concern about it.
texts now. They were all in the same classes last year, ate lunch together every day, and went to the mall after school.
As the year went on, however, Kimberly’s mother would not let her hang out after school. Instead, Kimberly had to come home and do her homework.
What does Kimberly’s experience at home tell you about her family life?
It was true that more than anything else, she wanted to be a lawyer when she grew up and wanted to get a
scholarship
Scholarship: (noun) A grant or payment made to support a student’s education, awarded on the basis of academic or other achievement.
to a good school, but it was also true that it was really hard for her to tell her friends. She could feel that something was wrong—almost like they were
insulted
insult: (verb) Speak to or treat with disrespect or scornful abuse.
.
What is most important to Kimberly?
When eighth grade started, Kimberly was placed in advanced academic classes and none of her old friends were in any of her classes anymore.
How do you think this made Kimberly feel to be apart from her friends?
After just a few weeks, she began to notice her friends ignoring her. There were a few times that she tried to hang out with them before class, and coldly they just moved away from her.
Why do you think her friends started ignoring her?
After a few more weeks, she started reading
rumors
rumors: (n.) A statement or report current without known authority for its truth.
and seeing
humiliating
Humiliation: to make (someone) ashamed or embarrassed.
photos on Snapchat.
If you read these rumors or saw these photos, how would you respond to help Kimberly?
Reach Out
There’s a number of things you can do to help Kimberly in this situation.
You can post words of support to Kimberly and encourage her to get help.
You can take screenshots and reporting the incident to an adult or even police.
Quest 1 Part 4: Cyberbullying
Write to the Point
Learning Checklist
Describe a time when you saw cyberbullying take place
Now that you’ve explored Kimberly’s story, it’s time to reflect on your own experiences.
Tell a story of a time when you saw cyberbullying take place.
Click for hints
Heads Up
What was the cyberbullying incident that you saw?
Where did the situation occur (Facebook, Snapchat, Instagram, text message)?
Describe the beginning, middle, and end.
Who was threatened in this situation?
How did you feel?
What did you want to do and what did you do when you saw it happening?
What did other people do?
How might you have responded differently today if faced with the same situation?
Double Check
Did you start all your sentences with a capital letter?
Did you include a subject and a verb in all your sentences?
Did you end your sentences with a period, question mark, or exclamation point?
Do your subject and verb agree?
Plural Noun boys play girls sing women drive men cook
Singular Noun boy plays girl sings woman drives man cooks
Bullseye
Before you submit, use the mouse (right-click) to copy and paste your journal into Word, do a spell and grammar check, then paste it back into the text box and click Submit.
Writing Sample
I started going to a new high school and had to ride the bus to get there. Greg and his friends from the football team were these older kids and every time I sat down they told me to get up and threw their backpacks on all the empty seats. They pushed me down the aisle, and every time the bus driver screamed at me to sit down so she could drive.
I didn’t know who to talk to, but I found myself telling my English teacher, Ms. Stevens. She told me that she could talk to Greg, that she knew him well. Then she said she would make a deal with me, if I started an anti-bullying campaign—shared stories with other kids of what happens to the whole group when we let kids bully other kids, asked them to help me write signs to post all over, and stand together whenever we see bullying. I did that and after my first year here, I was voted vice-president of the class.
Quest 1 Part 4: Cyberbullying
We Got Game
Quest 1 Part 4: Cyberbullying
Challenge Yourself
Learning Checklist
Explain what makes cyberbullying different from other aggressive acts
Identify the harmful effects of cyber-attacks
Describe what upstanders can do to build a strong digital community
Know your rights and how to defend yourself and others
Cyberbullying is bullying by use of technology, such as cell phones, computers, or tablets.
That’s correct. Cyberbullying differs from face-to-face bullying in that it can be done through use of technology.
Try again. Think about what the word “cyber” means.
In what ways is cyberbullying different and perhaps more dangerous from other forms of bullying?
Correct, but is just one example. Cyberbullying can be anonymous. Because of this, bullies cannot see the reactions of their victims and studies have shown that they feel less remorse (Peebles, 2014). Can you find any others?
Correct, but is just one example. Students are more vulnerable to long-term and long-lasting effects: those who post without thinking can be subject to criminal suits, and those who are targets can suffer more serious health issues. Can you find any others?
Correct, but is just one example. A larger and accepting passive audience can cause deeper humiliation. On the other hand, if that audience is aware and informed, this may improve the likelihood that someone might stand up for the target. See if you can find other ways.
You got it! Cyberbullying can be anonymous, is continuous and permanent in that it can occur 24/7, and can reach a large number of people.
True or False: Sharing a post making fun of someone on social media is considered cyberbullying.
That’s correct. Targeting people on social media is an example of cyberbullying.
Try again. Think about what it means to make fun of someone.
True or False: Cyberbullying can only occur while students are at school.
Try again. Since cyberbullying is done through technology, in can happen anywhere technology is accessible.
That’s correct. Cyberbullying can occur anywhere you can view, participate in or share content online, such as: text, apps, social media, forums, or gaming.
What can you do to help others if you see them being bullied online?
That’s correct! You have the power to help break the bullying cycle by speaking out when you see cyberbullying take place.
Try again. Staying silent can allow the bullying cycle to continue. If you are a bystander to bullying, you can help break the cycle by calling it out.
How can you protect yourself and others from cyberbullying?
That’s correct, but there are other ways. Can you find any other examples of how to protect yourself and others?
That’s correct, but there are other ways. Can you find any other examples of how to protect yourself and others?
That’s correct, but there are other ways. Can you find any other examples of how to protect yourself and others?
That’s correct! There are lots of ways you can protect yourself and others from cyberbullying.
Congratulations!
You’ve made it one more step in your journey toward being an upstander!


Adapter Pattern
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
by id v1.0
by class name v1.0
by tag name v1.0
by id v2.0
by class name v1.0
by tag name v1.0


Of the first 20 users who joined StackOverflow last month, how many of those users have asked a question?
How many of those questions have been answered?
Have any of these users asked multiple questions?
How many users have joined StackOverflow in the last month?
How many questions have been asked on StackOverflow in the last month?


This pattern demonstrates rhythmic circularity by fading out subsets of notes while increasing tempo to evolve the result through reorderings of its notes.
Start with a kernel, and make a cycle of kernels from it.
A kernel is the principal input of Hafuhafu. It's a short, repeating melody / ostinato / rhythm / contour / whatever.
Each next kernel is the previous one, just with every other note removed. They have the same total notes though, because you keep playing it over and over, so as long as the kernel length is odd, all elements are preserved, so now they are simply in a new order.
For example a kernel [1,2,3,4,5] would become [2,4,1,3,5] because if you look at a sequence of [1,2,3,4,5] repeating:
...1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5...
and now take every other note:
...2,4,1,3,5,2,4,1,3,5,2,4,1,3,5,2,4,1,3,5...
you can see we have a new repeating pattern. Same elements, different order.
Now, if we simply dropped every other note, the notes in the new pattern would last twice as long, so the music would seem to go half as fast. However, if we gradually increase the tempo to offset this impact, doubling it by the time we have faded out the departing notes, then we arrive at a place very similar to where we started.
We could repeat this process indefinitely. [2,4,1,3,5] in turn becomes [4,3,2,1,5] which in turn becomes [3,1,4,2,5] which in turn returns to[1,2,3,4,5]. That's a kernel cycle.
You don't always have to take just every other note. If you take every third note instead, that's sieve of 3.
Each time a kernel has evolved into the next kernel, an iteration has completed.
Each iteration usually has several layers at different speeds, or pitches, or volumes. Each layer usually spans multiple iterations, changing speed, pitch, or volume across them. Once you go down to a single layer, the effect is lost, whether in Droste or Zeno mode.
As the layer count increases, the sieve layers on top of itself. Some notes have only been sieved once, others twice, still others thrice. The more you've been sieved, the more gone you are.
Two modes: Droste and Zeno. Two different popular conceptions of infinite process.
In Droste mode, you are barreling through a tunnel of kernels within kernels. The previous one disappears around your periphery; the destination is infinitesimal in the distance. Layers fade in from nothing, have their day in the sun, then fade back out to nothing. Each iteration's inactive layer is silent. It stands in the place for all the layers yet to come, still too far away and quiet to hear.
In Zeno mode, you asymptotically approach a destination, but will never reach it. Half of the notes keep dying away, but half always still remain. Each iteration's inactive layer is at full gain. It stands in the place of all the layers yet to come, still to far away for us to know which ones are soonest to die next.
Droste seems to need an additional layer to sound as dense as Zeno, and that's because it's inactive layer is silent where Zeno's is at full gain. By inactive layer I mean the one which is stable / unchanging in pitch, gain, and/or duration.
Progress gets measured in a few different ways, but all of them are normalized to a scalar between 0 and 1:
- Element: A flat ratio of how many elements you are through the iteration to the total elements
of the iteration, without respect to how long the notes are.
- Duration: Taking into account the duration of the notes (so if the pattern is slowing down, your
duration progress
will be ahead of the element progress at first before they catch up and tie at the end of
each iteration).
- Layer: If a layer spans 3 iterations, then it would be at layer progress 1/3 by the end of the
first, 2/3 by the end of the second, and 3/3 by the end of the third.
Each of these progresses are helpful for calculating different things throughout the process.
By default Hafuhafu speeds up and fades out, but you can also slow down and fade in!


const ( // InitOnFirstAccess specifies that the reference should be initialized the first time it is accessed InitOnFirstAccess time.Duration = time.Duration(-1) // InitImmediately specifies that the reference should be initialized immediately after it is created InitImmediately time.Duration = time.Duration(0) )
func WithAbsoluteExpiration(value time.Duration) options.Opt
WithAbsoluteExpiration sets the expiration time for the reference. It will expire after this time period, regardless of whether or not it has been recently accessed.
func WithExpirationProvider(expirationProvider ExpirationProvider, expiryType ExpirationType) options.Opt
WithExpirationProvider sets the expiration provider, which determines the expiration time of the reference
func WithFinalizer(finalizer Finalizer) options.Opt
WithFinalizer sets a finalizer function that is called when the reference is closed or if it expires
func WithIdleExpiration(value time.Duration) options.Opt
WithIdleExpiration sets the idle-time expiration for the reference. The reference is expired after not being accessed for the given duration.
func WithRefreshInterval(initialInit, refreshPeriod time.Duration) options.Opt
WithRefreshInterval specifies that the reference should be proactively refreshed. Argument, initialInit, if greater than or equal to 0, indicates that the reference should be initialized after this duration. If less than 0, the reference will be initialized on first access. Argument, refreshPeriod, is the period at which the reference will be refreshed. Note that the Finalizer will not be invoked each time the value is refreshed.
ExpirationProvider is a function that returns the expiration time of a reference
type ExpirationProvider func() time.Duration
func NewGraduatingExpirationProvider(initialExpiry, increments, maxExpiry time.Duration) ExpirationProvider
NewGraduatingExpirationProvider returns an expiration provider that has an initial expiration and then expires in graduated increments with a maximum expiration time.
func NewSimpleExpirationProvider(expiry time.Duration) ExpirationProvider
NewSimpleExpirationProvider returns an expiration provider that sets the given expiration period
ExpirationType indicates how to handle expiration of the reference
type ExpirationType uint
const ( // LastAccessed specifies that the expiration time is calculated // from the last access time LastAccessed ExpirationType = iota // LastInitialized specifies that the expiration time is calculated // from the time the reference was initialized LastInitialized // Refreshing indicates that the reference should be periodically refreshed Refreshing )
Finalizer is a function that is called when the reference is closed
type Finalizer func(value interface{})
Initializer is a function that initializes the value
type Initializer func() (interface{}, error)
InitializerWithData is a function that initializes the value using the optional data.
type InitializerWithData func(data interface{}) (interface{}, error)
Reference holds a value that is initialized on first access using the provided Initializer function. The Reference has an optional expiring feature wherin the value is reset after the provided period of time. A subsequent call to Get or MustGet causes the Initializer function to be invoked again. The Reference also has a proactive refresh capability, in which the Initializer function is periodically called out of band (out of band means that the caller of Get or MustGet does not need to wait for the initializer function to complete: the old value will be used until the new value has finished initializing). An optional Finalizer function may be provided to be invoked whenever the Reference is closed (via a call to Close) or if it expires. (Note: The Finalizer function is not called every time the value is refreshed with the periodic refresh feature.)
type Reference struct {
// contains filtered or unexported fields
}
▹ Example
▹ Example (Expiring)
▹ Example (Refreshing)
func New(initializer Initializer, opts ...options.Opt) *Reference
New creates a new reference
func NewWithData(initializer InitializerWithData, opts ...options.Opt) *Reference
NewWithData creates a new reference where data is passed from the Get function to the initializer. This is useful for refreshing the reference with dynamic data.
func (r *Reference) Close()
Close ensures that the finalizer (if provided) is called. Close should be called for expiring references and rerences that specify finalizers.
func (r *Reference) Get(data ...interface{}) (interface{}, error)
Get returns the value, or an error if the initialiser returned an error.
func (r *Reference) IsClosed() bool
IsClosed returns true if the referenced has been closed
func (r *Reference) MustGet() interface{}
MustGet returns the value. If an error is returned during initialization of the value then this function will panic.
func (p *Reference) SetAbsoluteExpiration(expiration time.Duration)
func (p *Reference) SetExpirationProvider(expirationProvider ExpirationProvider, expiryType ExpirationType)
func (p *Reference) SetFinalizer(value Finalizer)
func (p *Reference) SetIdleExpiration(expiration time.Duration)
func (p *Reference) SetRefreshInterval(initialInit, refreshPeriod time.Duration)


{% extends '../tutorials/tutbaselayout.html' %} {% load static %} {% block content %}
You may encounter situations, when a block of code needs to be executed several number of times. In general, statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.
Programming languages provide various control structures that allow for more complicated execution paths.
A loop statement allows us to execute a statement or group of statements multiple times. Given below is the general form of a loop statement in most of the programming languages −
C programming language provides the following types of loops to handle looping requirements.
| Sr. No. | Loop Type & Description |
|---|---|
| 1 | Repeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body. |
| 2 | Executes a sequence of statements multiple times and abbreviates the code that manages the loop variable. |
| 3 | It is more like a while statement, except that it tests the condition at the end of the loop body. |
| 4 | You can use one or more loops inside any other while, for, or do..while loop. |
Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.
C supports the following control statements.
| Sr. No. | Loop Type & Description |
|---|---|
| 1 | Terminates the loop or switch statement and transfers execution to the statement immediately following the loop or switch. |
| 2 | Causes the loop to skip the remainder of its body and immediately retest its condition prior to reiterating. |
| 3 | Transfers control to the labeled statement. |
A loop becomes an infinite loop if a condition never becomes false. The for loop is traditionally used for this purpose. Since none of the three expressions that form the 'for' loop are required, you can make an endless loop by leaving the conditional expression empty.
#include <stdio.h>
int main() {
for( ; ; ) {
printf("This loop will run forever.\n");
}
return 0;
}
When the conditional expression is absent, it is assumed to be true. You may have an initialization and increment expression, but C programmers more commonly use the for(;;) construct to signify an infinite loop.
NOTE − You can terminate an infinite loop by pressing Ctrl + C keys.
{% endblock %}


Home
About Me
Family
Pictures
Future Plans
My Future
Where I want to go to college: Rice
Education for college: Pre-med
Job: somewhere


Vernon hosting kindness and kinship conference
by Ben BulmerAn interfaith gathering representing religions from all over the globe is meeting in Vernon to spread its message of kindness and kinship in an evening of philosophical thought.
The Ahmadiyya Muslim Jama'at, Vernon, is holding the Absolute Justice Kindness a Kinship conference Nov. 25, bringing together religious representatives from half a dozen of the world's religions in an effort to promote “harmonious co-existence among members of Canada's cultural mosaic.”
According to an Ahmadiyya Muslim Jama'at press release, the event is being held “in light of the new and grave dangers becoming manifest in the world.” The event hopes to inspire confidence in Canadians and discuss practical and sustainable paths that can lead to world peace.
The free conference will feature Okanagan Indian Band Chief Byron Louis speaking from an aboriginal perspective along with Okanagan Sikh Temple priest Giani Gurpreet Singh talking from the perspective of Sikhism.
Four talks will come from various Christian representatives, addressing everything from the metaphysical perspective of Christianity to the Catholic Church. Judaism, Islam, Buddhism and the Baha'i faith will also have representatives speaking from the perspective of their individual faiths.
The event is being organized by the Vernon chapter of Ahmadiyya Muslim Jama'at, the world's largest Islamic organization founded in 1889. The group's motto is “love for all, hatred for none.”
The event takes place at the Greater Vernon Recreation Centre on Monday, Nov. 25, from 6 p.m. to 8:30 p.m. The event is free and includes dinner.
For more information go here.


Komodo. Contribute to StakedChain/komodo development by creating an account on GitHub.
line tree fiddy
Mylo14-Jan-19 01:07 AM
@smk762 - dracocanis ominator when you say "tokens" in that article you mean "coins"?
cos tokens are created from assetsCC, to create non-fungible and fungible tokens.
good morning
is rant.cryptocartography written with ghost?
sorry, it is. it is self hosted?
smk762 - dracocanis ominator14-Jan-19 02:46 AM
yes to all of the above. easy enough to change tokens to coins if needed. Open to any feedback if something is inaccurate, and I spotted a typo I'll be fixing later (decent != descent)
1
blackjok3r14-Jan-19 07:10 AM
Pushed massive update to po64staker repo. Tony's refactor broke a few things... Fixed those and also made stakerlib a module as per request of Alright. Makes code a little easier to follow. Tested to be all working on my end. @smk762 - dracocanis ominator If you can test them aswell with the coins I sent that would be good. Once you have a staker up, I can send some more coins to someone else to test. Dont want the chain to stall out by sending too many away at once.(edited)
I think the readme is good enough, may also not be lol. Will need a few extra people to test.(edited)
2
smk762 - dracocanis ominator14-Jan-19 07:13 AM
I missed the early pos64 testing, so should be a good set of fresh eyes on it while I figure it out.
blackjok3r14-Jan-19 07:13 AM
These scripts make it very easy lol
at least as easy as it can be
smk762 - dracocanis ominator14-Jan-19 07:13 AM
just rigging up an extra camera, and I'll get into it
blackjok3r14-Jan-19 07:14 AM
withdraw script requries latest update of stakedChain/komodo master branch to work.
smk762 - dracocanis ominator14-Jan-19 07:15 AM
all my nodes use the StakedNotary repo, will it work on that?
only one is a notary, the other two just got setup like that way back when
blackjok3r14-Jan-19 07:15 AM
yes that will work fine
blackjok3r14-Jan-19 07:32 AM
one thing maybe you will need to copu list.json to stakedNotary/komodo/master rather than ~/komodo/src` as the instructions say.
CMaurice14-Jan-19 08:17 AM
so you can stake on a NN?
(I thought not but don't remember where I read it)
blackjok3r14-Jan-19 08:19 AM
I think you can now yes... Issue was before the staker basically made the daemon unusable... never responded to RPC calls
It wouldnt be a great idea... But I cant see any reaon why, if you can spare a single core to stake on, it would not work. Bear in mind having 64 address's on a notary node without disabling teh wallet filter will lead to all kinds of crazy unexpected results.
Is it something we need to be easily able to enable and disable the wallet filter ? I think I can add this pretty easily.
Also I had an idea earlier... Apparnelty PoS64 works with VerusHash ... maybe verushash has enough hash power with the daemon miner to avoid this Equiahash not having enough hash rate to stop PoS % rising to 100% over time.
Might be an option for the 0BR chains to use VerusHash as their hashing alg? THe Verus V1 was pretty good on GPUs and CPUs and unless some one comes in trying FPGA mine a chain with 0BR I think it should be relativly safe.
2
smk762 - dracocanis ominator14-Jan-19 09:02 AM
runCommand error: system(/home/smk762/pos64staker/staker.py 6a5fd46a54df65fd46a5f46as54f654fda6f54a6sf CFEKPOS51) returned 256
did I use pk instead of pub?
also, the list.json, do the pks need to be imported?
blackjok3r14-Jan-19 09:10 AM
when you run genaddress.opy it creates new address in an endlkess loop until It has one for every segid... so they are all imported unless you take that list.json to another node or delete wallet.dat.
staker.py 6a5fd46a54df65fd46a5f46as54f654fda6f54a6sf CFEKPOS51
not surew what you have done here...
it should be staker.py <blockhash> <CHAIN>
in early tests I wasnt using blocknotify but copy pasting the block hash from stdout when It mines a block(edited)
smk762 - dracocanis ominator14-Jan-19 09:15 AM
thats just keyboard sham cos I'm paranoid
blackjok3r14-Jan-19 09:15 AM
maybe the path is wrong
Its possible the isntructions are even wrong...
I did pwd instide the directory where staker.py was and copy psted it
smk762 - dracocanis ominator14-Jan-19 09:16 AM
smk762@pool:~/pos64staker$ /home/smk762/pos64staker/staker.py 04926a689b756beea232cfe49a43bcb4875353639212f590ec180dd0b506d9a4 CFEKPOS51
Not our block, exit.
blackjok3r14-Jan-19 09:16 AM
yep... unless you mine the block it doesnt do anything
you need 100 blocks before your utxos are elegible
smk762 - dracocanis ominator14-Jan-19 09:16 AM
that was manual so path is ok
k, that might be it
blackjok3r14-Jan-19 09:17 AM
./komodo-cli -ac_name=CFEKPOS51 getbalance64
when they are all mature... I can turn off my staker temporarily so you have a higher chance to get a block if you want.
really need to get some other ndoes staking... as the chain has stalled out using just my one PC.. its frozen on me a few times now lol
smk762 - dracocanis ominator14-Jan-19 09:18 AM
yeah, immature.
except the 600 I had a from mining yesterady
blackjok3r14-Jan-19 09:18 AM
to speed things up a bit you can hit the chain with aGPU... ive pulled most of my PoW off teh chain not long ago
its sittinng around 80%
PoW diff will be very low
smk762 - dracocanis ominator14-Jan-19 09:20 AM
2019-01-14 09:19:21 AcceptBlockHeader ContextualCheckBlockHeader failed
2019-01-14 09:19:21 AcceptBlock AcceptBlockHeader error
2019-01-14 09:19:21 ERROR: ProcessNewBlock: AcceptBlock FAILED
2019-01-14 09:19:21 ERROR: ContextualCheckBlockHeader: forked chain 3191 older than last notarized (height 3225) vs
blackjok3r14-Jan-19 09:21 AM
WTF
how can a chain with 1 miner be ona fork
smk762 - dracocanis ominator14-Jan-19 09:21 AM
I started gpu, then had a look, not sure but could be the cause
blackjok3r14-Jan-19 09:22 AM
maybe pool is on old versiona nd needs resync?
very confusing....
smk762 - dracocanis ominator14-Jan-19 09:22 AM
yeah, could be.
didnt update
blackjok3r14-Jan-19 09:23 AM
shouldnt be any consensus changes ... but I struggle to understand how ther is a fork... either way i guess a resync will either fix it... or reefuse to sync
smk762 - dracocanis ominator14-Jan-19 09:24 AM
After start.sh I'll have to stop POS51 and start manually right?
blackjok3r14-Jan-19 09:24 AM
yes... using the start.sh scripts isnt currently suppotred...
you need to do listassetchain aprams and add everything manually
but if a PITA ... I think I can fix that though... maybe add an input to the start.sh asking for any extra params the user can paste/write in.
@webworker01
I need some help to be able to set up the redirect for a new explorer. I just got it all working, but I'm not sure how you do the nginx part to make kmdlabs.io work.
CFEKPOS51 explorer is here for the time being: http://<IP_ADDRESS>:3004/
file to edit will probably be in /etc/nginx/sites-enabled folder
then sudo service nginx restart
blackjok3r14-Jan-19 10:43 AM
ok will have a look at that soon, thanks for the help. This explored doesnt ened any special redirect filters like the cluster chains do.
smk762 - dracocanis ominator14-Jan-19 10:43 AM
if it doesn work, it'll tell ya
blackjok3r14-Jan-19 10:43 AM
lol
looks like I've got a VerusHash PoS 64 working too... at least the PoW part is so far
I saved all that for next time, thanks. I treied to make it so I could isntall a specific chain whithout shutting everything down... but all the ports get messed up... Not that ti takes long to reinstall all explorers
blackjok3r14-Jan-19 10:54 AM
VerusHash and ac_staked are not currently working... code takes wrong path and tries to stake with equihash solver
Might ahve figured out fix unless its been disabled for some particular reason.
As soon as it got to block 100, it just hit the diff wall and stalled.
blackjok3r14-Jan-19 11:11 AM
no utxos are elegible ever
smk762 - dracocanis ominator14-Jan-19 11:23 AM
Could not load list.json please make sure it is in the directory where komodod is located. Exiting
^Csmk762@pool:~/StakedNotary/komodo/master$ sudo find / |grep komodod
/home/smk762/StakedNotary/komodo/FSM_mempooltest/komodod
/home/smk762/StakedNotary/komodo/libscottFIX/komodod
/home/smk762/StakedNotary/komodo/master/komodod
/home/smk762/.komodo/CFEKX/komodod.pid
/home/smk762/.komodo/CFEKY/komodod.pid
/home/smk762/.komodo/CFEKMLT/komodod.pid
/home/smk762/komodo/src/.deps/komodod-bitcoind.Po
/home/smk762/komodo/src/komodod-bitcoind.o
/home/smk762/komodo/doc/man/komodod.1
/home/smk762/komodo/contrib/komodod.bash-completion
/usr/local/bin/komodod
smk762@pool:~/StakedNotary/komodo/master$ sudo find / |grep list.json
/home/smk762/SuperNET/iguana/help/InstantDEX_getswaplist.json
/home/smk762/pos64staker/list.json
/home/smk762/StakedNotary/komodo/FSM_mempooltest/list.json
/home/smk762/StakedNotary/komodo/libscottFIX/list.json
/home/smk762/.cargo/registry/index/github.com-1ecc6299db9ec823/yo/sy/yosys-netlist-json
/home/smk762/komodo/src/list.json
/home/smk762/komodo/list.json
/usr/local/bin/list.json
I've put list.json everywhere, but still gives that error
blackjok3r14-Jan-19 11:30 AM
hmmm
I wonder if you can print out the directory that staker.py is in?
thats where it needs to be... or you can change the path to it?


***<PHONE_NUMBER>sunmi01 ***
Q01) ****
Which part of this life cycle shows the adult organism?
(1) Q (2) R (3) S (4) T
Your answer : (2) Right answer : (2)